From 0a4abb7306d4cf0ddf4fad23acc37243916e2a32 Mon Sep 17 00:00:00 2001 From: Sam Hemelryk Date: Wed, 16 Dec 2009 02:00:48 +0000 Subject: [PATCH] mod-lesson MDL-21006 Huge refactoring of the lesson code The following are notable changes made in this commit * Lesson page type are now class based and extend an abstract class. This includes a class for the page type and a class for the creating/editing a instance of this page. * Converted all forms to mforms * Action script located in mod/action/* were worked into the above so far less switch statements and the action directory will be removed. * Implements a custom renderer * Converted everything to use page, output, and custom renderer methods * Replaced all deprecated methods incl. print_textarea conversions * Tried to cut down on excessive DB calls. Things worth noting: * The focus of this patch was on cleaning up the module not rewriting it, as such I have organized NOT rewritten. There are still many areas in the module where the code could be greatly improved however to do so would require a rethink/rewrite --- lang/en_utf8/help/lesson/displayleftif.html | 6 + lang/en_utf8/lesson.php | 34 +- mod/lesson/action/addbranchtable.php | 86 - mod/lesson/action/addcluster.php | 59 - mod/lesson/action/addendofbranch.php | 60 - mod/lesson/action/addendofcluster.php | 45 - mod/lesson/action/addpage.php | 198 -- mod/lesson/action/confirmdelete.php | 30 - mod/lesson/action/continue.html | 78 - mod/lesson/action/continue.php | 791 ------ mod/lesson/action/delete.php | 58 - mod/lesson/action/editpage.php | 473 ---- mod/lesson/action/insertpage.php | 167 -- mod/lesson/action/move.php | 40 - mod/lesson/action/moveit.php | 100 - mod/lesson/action/updatepage.php | 169 -- mod/lesson/backuplib.php | 920 ++++--- mod/lesson/continue.php | 199 ++ mod/lesson/db/access.php | 21 + mod/lesson/db/install.php | 29 +- mod/lesson/db/install.xml | 52 +- mod/lesson/db/upgrade.php | 136 +- mod/lesson/edit.php | 364 +-- mod/lesson/editpage.php | 104 + mod/lesson/editpage_form.php | 57 + mod/lesson/essay.php | 696 +++--- mod/lesson/essay_form.php | 64 + mod/lesson/format.php | 300 ++- mod/lesson/grade.php | 72 +- mod/lesson/highscores.php | 387 +-- mod/lesson/import.php | 161 +- mod/lesson/import_form.php | 74 + mod/lesson/importppt.php | 715 ++---- mod/lesson/importpptlib.php | 231 ++ mod/lesson/index.php | 164 +- mod/lesson/{styles.php => lesson.css} | 47 +- mod/lesson/lesson.php | 198 +- mod/lesson/lib.php | 2431 ++++++++++++++++++- mod/lesson/locallib.php | 1511 +----------- mod/lesson/mediafile.php | 253 +- mod/lesson/mod_form.php | 281 ++- mod/lesson/pagetypes/branchtable.php | 296 +++ mod/lesson/pagetypes/cluster.php | 176 ++ mod/lesson/pagetypes/endofbranch.php | 230 ++ mod/lesson/pagetypes/endofcluster.php | 197 ++ mod/lesson/pagetypes/essay.php | 270 ++ mod/lesson/pagetypes/matching.php | 513 ++++ mod/lesson/pagetypes/multichoice.php | 503 ++++ mod/lesson/pagetypes/numerical.php | 282 +++ mod/lesson/pagetypes/shortanswer.php | 349 +++ mod/lesson/pagetypes/truefalse.php | 317 +++ mod/lesson/reformat.php | 21 +- mod/lesson/renderer.php | 669 +++++ mod/lesson/report.php | 1346 ++++------ mod/lesson/restorelib.php | 144 +- mod/lesson/settings.php | 65 + mod/lesson/tabs.php | 123 +- mod/lesson/timer.js | 8 +- mod/lesson/version.php | 23 +- mod/lesson/view.php | 1357 ++++------- mod/lesson/view_form.php | 53 + 61 files changed, 10475 insertions(+), 8328 deletions(-) create mode 100644 lang/en_utf8/help/lesson/displayleftif.html delete mode 100644 mod/lesson/action/addbranchtable.php delete mode 100644 mod/lesson/action/addcluster.php delete mode 100644 mod/lesson/action/addendofbranch.php delete mode 100644 mod/lesson/action/addendofcluster.php delete mode 100644 mod/lesson/action/addpage.php delete mode 100644 mod/lesson/action/confirmdelete.php delete mode 100644 mod/lesson/action/continue.html delete mode 100644 mod/lesson/action/continue.php delete mode 100644 mod/lesson/action/delete.php delete mode 100644 mod/lesson/action/editpage.php delete mode 100644 mod/lesson/action/insertpage.php delete mode 100644 mod/lesson/action/move.php delete mode 100644 mod/lesson/action/moveit.php delete mode 100644 mod/lesson/action/updatepage.php create mode 100644 mod/lesson/continue.php create mode 100644 mod/lesson/editpage.php create mode 100644 mod/lesson/editpage_form.php create mode 100644 mod/lesson/essay_form.php create mode 100644 mod/lesson/import_form.php create mode 100644 mod/lesson/importpptlib.php rename mod/lesson/{styles.php => lesson.css} (88%) create mode 100644 mod/lesson/pagetypes/branchtable.php create mode 100644 mod/lesson/pagetypes/cluster.php create mode 100644 mod/lesson/pagetypes/endofbranch.php create mode 100644 mod/lesson/pagetypes/endofcluster.php create mode 100644 mod/lesson/pagetypes/essay.php create mode 100644 mod/lesson/pagetypes/matching.php create mode 100644 mod/lesson/pagetypes/multichoice.php create mode 100644 mod/lesson/pagetypes/numerical.php create mode 100644 mod/lesson/pagetypes/shortanswer.php create mode 100644 mod/lesson/pagetypes/truefalse.php create mode 100644 mod/lesson/renderer.php create mode 100644 mod/lesson/settings.php create mode 100644 mod/lesson/view_form.php diff --git a/lang/en_utf8/help/lesson/displayleftif.html b/lang/en_utf8/help/lesson/displayleftif.html new file mode 100644 index 0000000000..9f71767599 --- /dev/null +++ b/lang/en_utf8/help/lesson/displayleftif.html @@ -0,0 +1,6 @@ +

Display left menu: grade condition

+ +

By specifying a grade greater than 0, the user taking the lesson must have a grade equal to +or greater than the grade set in order to view the Left Menu.

+

This allows Lesson designers to force users to go through the entire lesson during the user's first attempt. +Then, if a user retakes the Lesson after meeting the required grade they can see the left menu to help with review.

\ No newline at end of file diff --git a/lang/en_utf8/lesson.php b/lang/en_utf8/lesson.php index 51bc5534c0..a4da9a47aa 100644 --- a/lang/en_utf8/lesson.php +++ b/lang/en_utf8/lesson.php @@ -9,6 +9,7 @@ $string['activitylinkname'] = 'Go to: $a'; $string['addabranchtable'] = 'Add a Branch Table'; $string['addbranchtable'] = 'Add a Branch Table'; $string['addanendofbranch'] = 'Add an End of Branch'; +$string['addanewpage'] = 'Add a new page'; $string['addaquestionpage'] = 'Add a Question Page'; $string['addaquestionpagehere'] = 'Add a question page here'; $string['addcluster'] = 'Add a Cluster'; @@ -33,6 +34,7 @@ $string['available'] = 'Available from'; $string['averagescore'] = 'Average score'; $string['averagetime'] = 'Average time'; $string['branchtable'] = 'Branch Table'; +$string['branch'] = 'Branch'; $string['cannotfindanswer'] = 'Cannot find answer'; $string['cannotfindattempt'] = 'Error: could not find attempt'; $string['cannotfindessay'] = 'Error: could not find essay'; @@ -61,6 +63,7 @@ $string['checkquestion'] = 'Check question'; $string['classstats'] = 'Class statistics'; $string['clicktodownload'] = 'Click on the following link to download the file.'; $string['clicktopost'] = 'Click here to post your grade on the High Scores list.'; +$string['cluster'] = 'Cluster'; $string['clusterjump'] = 'Unseen question within a cluster'; $string['clustertitle'] = 'Cluster'; $string['collapsed'] = 'Collapsed'; @@ -69,6 +72,15 @@ $string['completed'] = 'Completed'; $string['completederror'] = 'Complete the lesson'; $string['completethefollowingconditions'] = 'You must complete the following condition(s) in $a lesson before you can proceed.'; $string['conditionsfordependency'] = 'Condition(s) for the dependency'; +$string['configactionaftercorrectanswer']= 'The default action to take after a correct answer'; +$string['configmaxanswers']= 'Default maximum number of answers/branches per page'; +$string['configmaxhighscores']= 'Number of high scores displayed'; +$string['configmediaclose']= 'Displays a close button as part of the popup generated for a linked media file'; +$string['configmediaheight']= 'Sets the height of the popup displayed for a linked media file'; +$string['configmediawidth']= 'Sets the width of the popup displayed for a linked media file'; +$string['configslideshowbgcolor']= 'Background color to for the slideshow if it is enabled'; +$string['configslideshowheight']= 'Sets the height of the slideshow if it is enabled'; +$string['configslideshowwidth']= 'Sets the width of the slideshow if it is enabled'; $string['confirmdelete']= 'Delete page'; $string['confirmdeletionofthispage'] = 'Confirm deletion of this page'; $string['congratulations'] = 'Congratulations - end of lesson reached'; @@ -95,19 +107,22 @@ $string['displayhighscores'] = 'Display high scores'; $string['displayinleftmenu'] = 'Display in left menu?'; $string['displayleftif'] = 'Display left menu only if grade greater than:'; $string['displayleftmenu'] = 'Display left menu'; +$string['displayleftmenuif'] = 'Display left menu: grade condition'; $string['displayofgrade'] = 'Display of grade (for students only)'; $string['displayreview'] = 'Display review button'; $string['displayscorewithessays'] = 'You earned $a->score out of $a->tempmaxgrade for the automatically graded questions.
Your $a->essayquestions essay question(s) will be graded and added
into your final score at a later date.

Your current grade without the essay question(s) is $a->score out of $a->grade'; $string['displayscorewithoutessays'] = 'Your score is $a->score (out of $a->grade).'; $string['edit'] = 'Edit'; +$string['editingquestionpage'] = 'Editing $a question page'; $string['editpage'] = 'Edit page contents'; $string['editlessonsettings'] = 'Edit lesson settings'; $string['editpagecontent'] = 'Edit page contents'; $string['email'] = 'Email'; -$string['emailallgradedessays'] = 'Email ALL
graded essays'; +$string['emailallgradedessays'] = 'Email ALL graded essays'; $string['emailgradedessays'] = 'Email graded essays'; $string['emailsuccess'] = 'Emails sent successfully'; $string['endofbranch'] = 'End of branch'; +$string['endofcluster'] = 'End of cluster'; $string['endofclustertitle'] = 'End of cluster'; $string['endoflesson'] = 'End of lesson'; $string['enteredthis'] = 'entered this.'; @@ -144,6 +159,7 @@ $string['importppt'] = 'Import PowerPoint'; $string['importquestions'] = 'Import questions'; $string['insertedpage'] = 'Inserted page'; $string['invalidpageid'] = 'Invalid lesson page ID'; +$string['invalidfile'] = 'Invalid file'; $string['invalidid'] = 'No course module ID or lesson ID were passed'; $string['invalidlessonid'] = 'lesson ID was incorrect'; $string['invalidpageid'] = 'Invalid Page ID'; @@ -174,6 +190,8 @@ $string['lowscore'] = 'Low score'; $string['lowtime'] = 'Low time'; $string['manualgrading'] = 'Grade Essays'; $string['matchesanswer'] = 'Matches with answer'; +$string['matching'] = 'Matching'; +$string['matchingpair'] = 'Matching pair $a'; $string['maxhighscores'] = 'Number of high scores displayed'; $string['maximumnumberofanswersbranches'] = 'Maximum number of answers/branches'; $string['maximumnumberofattempts'] = 'Maximum number of attempts'; @@ -183,8 +201,8 @@ $string['maxtimewarning'] = 'You have $a minute(s) to finish the lesson.'; $string['mediaclose'] = 'Show close button:'; $string['mediafile'] = 'Pop-up to file or web page'; $string['mediafilepopup'] = 'Click here to view'; -$string['mediaheight'] = 'Window height:'; -$string['mediawidth'] = 'width:'; +$string['mediaheight'] = 'Popup window height:'; +$string['mediawidth'] = 'Popup window width:'; $string['minimumnumberofquestions'] = 'Minimum number of questions'; $string['missingname'] = 'Please enter a nickname'; $string['modattempts'] = 'Allow student review'; @@ -196,9 +214,11 @@ $string['movedpage'] = 'Moved page'; $string['movepagehere'] = 'Move page to here'; $string['moving'] = 'Moving page: $a'; $string['multianswer'] = 'Multianswer'; +$string['multichoice'] = 'Multichoice'; $string['multipleanswer'] = 'Multiple Answer'; $string['nameapproved'] = 'Name approved'; $string['namereject'] = 'Sorry, your name has been rejected by the filter.
Please try another name.'; +$string['new'] = 'new'; $string['nextpage'] = 'Next page'; $string['noanswer'] = 'No answer given. Please go back and submit an answer.'; $string['noattemptrecordsfound'] = 'No attempt records found: no grade given'; @@ -226,10 +246,12 @@ $string['numberofcorrectmatches'] = 'Number of correct matches: $a'; $string['numberofpagestoshow'] = 'Number of pages (cards) to show'; $string['numberofpagesviewed'] = 'Number of questions answered: $a'; $string['numberofpagesviewednotice'] = 'Number of questions answered: $a->nquestions; (You should answer at least: $a->minquestions)'; +$string['numerical'] = 'Numerical'; $string['onpostperpage'] = 'Only one posting per grade'; $string['ongoing'] = 'Display ongoing score'; $string['ongoingcustom'] = 'You have earned $a->score point(s) out of $a->currenthigh point(s) thus far.'; $string['ongoingnormal'] = 'You have answered $a->correct correctly out of $a->viewed attempts.'; +$string['options'] = 'Options'; $string['or'] = 'OR'; $string['ordered'] = 'Ordered'; $string['other'] = 'Other'; @@ -247,6 +269,7 @@ $string['pleaseenteryouranswerinthebox'] = 'Please enter your answer in the box' $string['pleasematchtheabovepairs'] = 'Please match the above pairs'; $string['pointsearned'] = 'Points earned'; $string['postsuccess'] = 'Post successful'; +$string['pptsuccessfullimport'] = 'Successfully imported pages from the uploaded PowerPoint Presentation'; $string['practice'] = 'Practice lesson'; $string['preprocesserror'] = 'Error occurred during pre-processing!'; $string['processerror'] = 'Error occurred during processing!'; @@ -285,8 +308,10 @@ $string['savepage'] = 'Save page'; $string['score'] = 'Score'; $string['scores'] = 'Scores'; $string['secondpluswrong'] = 'Not quite. Would you like to try again?'; +$string['selectaqtype'] = 'Select a question type'; $string['showanunansweredpage'] = 'Show an unanswered Page'; $string['showanunseenpage'] = 'Show an Unseen Page'; +$string['shortanswer'] = 'Short answer'; $string['singleanswer'] = 'Single Answer'; $string['skip'] = 'Skip navigation'; $string['slideshow'] = 'Slide Show'; @@ -312,6 +337,9 @@ $string['timespenterror'] = 'Spend at least $a minutes in the lesson'; $string['timespentminutes'] = 'Time Spent (minutes)'; $string['timetaken'] = 'Time taken'; $string['topscorestitle'] = 'Top $a High Scores'; +$string['truefalse'] = 'True/False'; +$string['unabledtosavefile'] = 'The file you uploaded could not be saved'; +$string['unknownqtypesnotimported'] = '$a questions with unsupported question types were not imported'; $string['unseenpageinbranch'] = 'Unseen question within a branch'; $string['unsupportedqtype'] = 'Unsupported question type ($a)!'; $string['updatedpage'] = 'Updated page'; diff --git a/mod/lesson/action/addbranchtable.php b/mod/lesson/action/addbranchtable.php deleted file mode 100644 index 92ebafc505..0000000000 --- a/mod/lesson/action/addbranchtable.php +++ /dev/null @@ -1,86 +0,0 @@ -get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0))) { - print_error('cannotfindfirstpage', 'lesson'); - } - while (true) { - if ($apageid) { - $title = $DB->get_field("lesson_pages", "title", array("id" => $apageid)); - $jump[$apageid] = $title; - $apageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $apageid)); - } else { - // last page reached - break; - } - } - } - // give teacher a blank proforma - $helpicon = new moodle_help_icon(); - $helpicon->text = get_string("addabranchtable", "lesson"); - $helpicon->page = "overview"; - $helpicon->module = "lesson"; - echo $OUTPUT->heading_with_help($helpicon); - - ?> -
-
- - - - - - - - - \n"; - echo "\n"; - for ($i = 0; $i < $lesson->maxanswers; $i++) { - $iplus1 = $i + 1; - echo "\n"; - echo "\n"; - } - // close table and form - ?> -

-
"; - echo get_string("pagecontents", "lesson").":
\n"; - print_textarea($usehtmleditor, 25,70, 0, 0, "contents"); - echo "
\n"; - echo "
"; - echo get_string("arrangebuttonshorizontally", "lesson")."\n"; - echo "
"; - echo get_string("displayinleftmenu", "lesson"); - echo "
\n"; - echo "
".get_string("description", "lesson")." $iplus1:
\n"; - print_textarea(false, 10, 70, 630, 300, "answer[$i]"); - echo "
".get_string("jump", "lesson")." $iplus1: \n"; - if ($i) { - // answers 2, 3, 4... jumpto this page - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - } else { - // answer 1 jumpto next page - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", LESSON_NEXTPAGE, false)); - } - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - echo "

- " /> - " /> -
-
diff --git a/mod/lesson/action/addcluster.php b/mod/lesson/action/addcluster.php deleted file mode 100644 index 8a3a709092..0000000000 --- a/mod/lesson/action/addcluster.php +++ /dev/null @@ -1,59 +0,0 @@ -get_record("lesson_pages", array("prevpageid" => 0, "lessonid" => $lesson->id))) { - print_error('cannotfindpagerecord', 'lesson'); - } - } else { - if (!$page = $DB->get_record("lesson_pages", array("id" => $pageid))) { - print_error('cannotfindpagerecord', 'lesson'); - } - } - $newpage = new stdClass; - $newpage->lessonid = $lesson->id; - $newpage->prevpageid = $pageid; - if ($pageid != 0) { - $newpage->nextpageid = $page->nextpageid; - } else { - $newpage->nextpageid = $page->id; - } - $newpage->qtype = LESSON_CLUSTER; - $newpage->timecreated = $timenow; - $newpage->title = get_string("clustertitle", "lesson"); - $newpage->contents = get_string("clustertitle", "lesson"); - $newpageid = $DB->insert_record("lesson_pages", $newpage); - // update the linked list... - if ($pageid != 0) { - $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); - } - - if ($pageid == 0) { - $page->nextpageid = $page->id; - } - if ($page->nextpageid) { - // the new page is not the last page - $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); - } - // ..and the single "answer" - $newanswer = new stdClass; - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $newpageid; - $newanswer->timecreated = $timenow; - $newanswer->jumpto = LESSON_CLUSTERJUMP; - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - lesson_set_message(get_string('addedcluster', 'lesson'), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - diff --git a/mod/lesson/action/addendofbranch.php b/mod/lesson/action/addendofbranch.php deleted file mode 100644 index b6bb3be4c0..0000000000 --- a/mod/lesson/action/addendofbranch.php +++ /dev/null @@ -1,60 +0,0 @@ -get_record("lesson_pages", array("id" => $pageid))) { - print_error('cannotfindpagerecord', 'lesson'); - } - // chain back up to find the (nearest branch table) - $btpageid = $pageid; - if (!$btpage = $DB->get_record("lesson_pages", array("id" => $btpageid))) { - print_error('cannotfindpagerecord', 'lesson'); - } - while (($btpage->qtype != LESSON_BRANCHTABLE) AND ($btpage->prevpageid > 0)) { - $btpageid = $btpage->prevpageid; - if (!$btpage = $DB->get_record("lesson_pages", array("id" => $btpageid))) { - print_error('cannotfindpagerecord', 'lesson'); - } - } - if ($btpage->qtype == LESSON_BRANCHTABLE) { - $newpage = new stdClass; - $newpage->lessonid = $lesson->id; - $newpage->prevpageid = $pageid; - $newpage->nextpageid = $page->nextpageid; - $newpage->qtype = LESSON_ENDOFBRANCH; - $newpage->timecreated = $timenow; - $newpage->title = get_string("endofbranch", "lesson"); - $newpage->contents = get_string("endofbranch", "lesson"); - $newpageid = $DB->insert_record("lesson_pages", $newpage); - // update the linked list... - $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); - if ($page->nextpageid) { - // the new page is not the last page - $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); - } - // ..and the single "answer" - $newanswer = new stdClass; - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $newpageid; - $newanswer->timecreated = $timenow; - $newanswer->jumpto = $btpageid; - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - - lesson_set_message(get_string('addedanendofbranch', 'lesson'), 'notifysuccess'); - } else { - lesson_set_message(get_string('nobranchtablefound', 'lesson')); - } - - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - diff --git a/mod/lesson/action/addendofcluster.php b/mod/lesson/action/addendofcluster.php deleted file mode 100644 index 41509501cd..0000000000 --- a/mod/lesson/action/addendofcluster.php +++ /dev/null @@ -1,45 +0,0 @@ -get_record("lesson_pages", array("id" => $pageid))) { - print_error('cannotfindpages', 'lesson'); - } - - // could put code in here to check if the user really can insert an end of cluster - - $newpage = new stdClass; - $newpage->lessonid = $lesson->id; - $newpage->prevpageid = $pageid; - $newpage->nextpageid = $page->nextpageid; - $newpage->qtype = LESSON_ENDOFCLUSTER; - $newpage->timecreated = $timenow; - $newpage->title = get_string("endofclustertitle", "lesson"); - $newpage->contents = get_string("endofclustertitle", "lesson"); - $newpageid = $DB->insert_record("lesson_pages", $newpage); - // update the linked list... - $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); - if ($page->nextpageid) { - // the new page is not the last page - $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); - } - // ..and the single "answer" - $newanswer = new stdClass; - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $newpageid; - $newanswer->timecreated = $timenow; - $newanswer->jumpto = LESSON_NEXTPAGE; - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - lesson_set_message(get_string('addedendofcluster', 'lesson'), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); diff --git a/mod/lesson/action/addpage.php b/mod/lesson/action/addpage.php deleted file mode 100644 index 4ba7ca6428..0000000000 --- a/mod/lesson/action/addpage.php +++ /dev/null @@ -1,198 +0,0 @@ -id, $pageid)) { - $jump[LESSON_UNSEENBRANCHPAGE] = get_string("unseenpageinbranch", "lesson"); - $jump[LESSON_RANDOMPAGE] = get_string("randompageinbranch", "lesson"); - } - if(lesson_display_cluster_jump($lesson->id, $pageid)) { - $jump[LESSON_CLUSTERJUMP] = get_string("clusterjump", "lesson"); - } - if (!optional_param('firstpage', 0, PARAM_INT)) { - $linkadd = ""; - $apageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0)); - - while (true) { - if ($apageid) { - $title = $DB->get_field("lesson_pages", "title", array("id" => $apageid)); - $jump[$apageid] = strip_tags(format_string($title,true)); - $apageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $apageid)); - } else { - // last page reached - break; - } - } - } else { - $linkadd = "&firstpage=1"; - } - - // give teacher a blank proforma - $helpicon = new moodle_help_icon(); - $helpicon->text = get_string("addaquestionpage", "lesson"); - $helpicon->page = "overview"; - $helpicon->module = "lesson"; - echo $OUTPUT->heading_with_help($helpicon); - - ?> -
-
- - - - - '.get_string("questiontype", "lesson").": \n"; - echo $OUTPUT->help_icon(moodle_help_icon::make("questiontypes", get_string("questiontype", "lesson"), "lesson"))."
"; - lesson_qtype_menu($LESSON_QUESTION_TYPE, $qtype, - "lesson.php?id=$cm->id&action=addpage&pageid=".$pageid.$linkadd); - - if ( $qtype == LESSON_SHORTANSWER || $qtype == LESSON_MULTICHOICE ) { // only display this option for Multichoice and shortanswer - echo '

'; - if ($qtype == LESSON_SHORTANSWER) { - $qoptionstr = get_string('casesensitive', 'lesson'); - } else { - $qoptionstr = get_string('multianswer', 'lesson'); - } - echo ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("questionoption", get_string("questionoption", "lesson"), "lesson")); - echo '

'; - } - ?> - - - - \n"; - switch ($qtype) { - case LESSON_TRUEFALSE : - for ($i = 0; $i < 2; $i++) { - $iplus1 = $i + 1; - echo "\n"; - echo "\n"; - echo "\n"; - } - break; - case LESSON_ESSAY : - echo "\n"; - break; - case LESSON_MATCHING : - for ($i = 0; $i < $lesson->maxanswers+2; $i++) { - $icorrected = $i - 1; - if ($i == 0) { - echo "\n"; - } elseif ($i == 1) { - echo "\n"; - } else { - echo "\n"; - echo "\n"; - } - if ($i == 2) { - echo "\n"; - } elseif ($i == 3) { - echo "\n"; - } - } - break; - case LESSON_SHORTANSWER : - case LESSON_NUMERICAL : - case LESSON_MULTICHOICE : - // default code - for ($i = 0; $i < $lesson->maxanswers; $i++) { - $iplus1 = $i + 1; - echo "\n"; - echo "\n"; - echo "\n"; - } - break; - } - // close table and form - ?> -

-
"; - echo get_string("pagecontents", "lesson").":
\n"; - print_textarea($usehtmleditor, 25,70, 630, 400, "contents"); - echo "
".get_string("answer", "lesson")." $iplus1:
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$i]"); - echo "
".get_string("response", "lesson")." $iplus1:
\n"; - print_textarea(false, 6, 70, 630, 300, "response[$i]"); - echo "
".get_string("jump", "lesson")." $iplus1: \n"; - if ($i) { - // answers 2, 3, 4... jumpto this page - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - } else { - // answer 1 jumpto next page - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", LESSON_NEXTPAGE, false)); - } - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - if ($i) { - echo get_string("score", "lesson")." $iplus1: "; - } else { - echo get_string("score", "lesson")." $iplus1: "; - } - } - echo "
".get_string("jump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[0]", LESSON_NEXTPAGE, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if ($lesson->custom) { - echo get_string("score", "lesson").": "; - } - echo "
".get_string("correctresponse", "lesson").":
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$i]"); - echo "
".get_string("wrongresponse", "lesson").":
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$i]"); - echo "
".get_string("answer", "lesson")." $icorrected:
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$i]"); - echo "
".get_string("matchesanswer", "lesson")." $icorrected:
\n"; - print_textarea(false, 6, 70, 630, 300, "response[$i]"); - echo "
".get_string("correctanswerjump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", LESSON_NEXTPAGE, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - echo get_string("correctanswerscore", "lesson").": "; - } - echo "
".get_string("wronganswerjump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - echo get_string("wronganswerscore", "lesson").": "; - } - echo "
".get_string("answer", "lesson")." $iplus1:
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$i]"); - echo "
".get_string("response", "lesson")." $iplus1:
\n"; - print_textarea(false, 6, 70, 630, 300, "response[$i]"); - echo "
".get_string("jump", "lesson")." $iplus1: \n"; - if ($i) { - // answers 2, 3, 4... jumpto this page - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - } else { - // answer 1 jumpto next page - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", LESSON_NEXTPAGE, false)); - } - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - if ($i) { - echo get_string("score", "lesson")." $iplus1: "; - } else { - echo get_string("score", "lesson")." $iplus1: "; - } - } - echo "

- " /> - " /> -
-
diff --git a/mod/lesson/action/confirmdelete.php b/mod/lesson/action/confirmdelete.php deleted file mode 100644 index 8daa9fee05..0000000000 --- a/mod/lesson/action/confirmdelete.php +++ /dev/null @@ -1,30 +0,0 @@ -get_record("lesson_pages", array ("id" => $pageid))) { - print_error('cannotfindpages', 'lesson'); - } - echo $OUTPUT->heading(get_string("deletingpage", "lesson", format_string($thispage->title))); - // print the jumps to this page - $params = array("lessonid" => $lesson->id, "pageid" => $pageid); - if ($answers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid AND jumpto = :pageid + 1", $params)) { - echo $OUTPUT->heading(get_string("thefollowingpagesjumptothispage", "lesson")); - echo "

\n"; - foreach ($answers as $answer) { - if (!$title = $DB->get_field("lesson_pages", "title", array("id" => $answer->pageid))) { - print_error('cannotfindpagetitle', 'lesson'); - } - echo $title."
\n"; - } - } - echo $OUTPUT->confirm(get_string("confirmdeletionofthispage","lesson"), - "lesson.php?action=delete&id=$cm->id&pageid=$pageid", - "view.php?id=$cm->id"); - diff --git a/mod/lesson/action/continue.html b/mod/lesson/action/continue.html deleted file mode 100644 index c2f612dcc5..0000000000 --- a/mod/lesson/action/continue.html +++ /dev/null @@ -1,78 +0,0 @@ - - -displayleft) { // Skip navigation anchor ?> - - - - - -ongoing) { - lesson_print_ongoing_score($lesson); - } -?> - - - -modattempts[$lesson->id])) { // User is modifying attempts - save button and some instructions ?> - -

- - - -

- -

-

- -

-

- -

-

- -

- -
- - -review && !$correctanswer && !$noanswer && !$isessayquestion) { // Review button back ?> - -
- - - -

- -

- -
- - - -
- - - -review && !$correctanswer && !$noanswer && !$isessayquestion) { // Review button continue ?> - -

- -

- - - -

- -

- - - -
diff --git a/mod/lesson/action/continue.php b/mod/lesson/action/continue.php deleted file mode 100644 index f14f267bef..0000000000 --- a/mod/lesson/action/continue.php +++ /dev/null @@ -1,791 +0,0 @@ -displayleft = lesson_displayleftif($lesson); - } - - // This is the code updates the lesson time for a timed test - // get time information for this user - $timer = new stdClass; - if (!has_capability('mod/lesson:manage', $context)) { - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if (!$timer = $DB->get_records_select('lesson_timer', "lessonid = :lessonid AND userid = :userid", $params, 'starttime')) { - print_error('Error: could not find records'); - } else { - $timer = array_pop($timer); // this will get the latest start time record - } - - if ($lesson->timed) { - $timeleft = ($timer->starttime + $lesson->maxtime * 60) - time(); - - if ($timeleft <= 0) { - // Out of time - lesson_set_message(get_string('eolstudentoutoftime', 'lesson')); - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=".LESSON_EOL."&outoftime=normal"); - die; // Shouldn't be reached, but make sure - } else if ($timeleft < 60) { - // One minute warning - lesson_set_message(get_string("studentoneminwarning", "lesson")); - } - } - - $timer->lessontime = time(); - $DB->update_record("lesson_timer", $timer); - } - - // record answer (if necessary) and show response (if none say if answer is correct or not) - $pageid = required_param('pageid', PARAM_INT); - if (!$page = $DB->get_record("lesson_pages", array("id" => $pageid))) { - print_error("Continue: Page record not found"); - } - // set up some defaults - $answerid = 0; - $noanswer = false; - $correctanswer = false; - $isessayquestion = false; // use this to turn off review button on essay questions - $newpageid = 0; // stay on the page - $studentanswer = ''; // use this to store student's answer(s) in order to display it on feedback page - switch ($page->qtype) { - case LESSON_ESSAY : - $isessayquestion = true; - if (!$useranswer = $_POST['answer']) { - $noanswer = true; - break; - } - $useranswer = clean_param($useranswer, PARAM_RAW); - - if (!$answers = $DB->get_records("lesson_answers", array("pageid" => $pageid), "id")) { - print_error("Continue: No answers found"); - } - $correctanswer = false; - foreach ($answers as $answer) { - $answerid = $answer->id; - $newpageid = $answer->jumpto; - } - /// 6/29/04 // - $userresponse->sent=0; - $userresponse->graded = 0; - $userresponse->score = 0; - $userresponse->answer = $useranswer; - $userresponse->response = ""; - $userresponse = serialize($userresponse); - - $studentanswer = s($useranswer); - break; - case LESSON_SHORTANSWER : - if (isset($_POST['answer'])) { - $useranswer = $_POST['answer']; - } else { - $noanswer = true; - break; - } - $useranswer = s(clean_param($useranswer, PARAM_RAW)); - if (!$answers = $DB->get_records("lesson_answers", array("pageid" => $pageid), "id")) { - print_error("Continue: No answers found"); - } - $i=0; - foreach ($answers as $answer) { - $i += 1; - $expectedanswer = $answer->answer; // for easier handling of $answer->answer - $ismatch = false; - $markit = false; - $useregexp = false; - - if ($page->qoption) { - $useregexp = true; - } - - if ($useregexp) { //we are using 'normal analysis', which ignores case - $ignorecase = ''; - if ( substr($expectedanswer,strlen($expectedanswer) - 2, 2) == '/i') { - $expectedanswer = substr($expectedanswer,0,strlen($expectedanswer) - 2); - $ignorecase = 'i'; - } - } else { - $expectedanswer = str_replace('*', '#####', $expectedanswer); - $expectedanswer = preg_quote($expectedanswer, '/'); - $expectedanswer = str_replace('#####', '.*', $expectedanswer); - } - // see if user typed in any of the correct answers - if ((!$lesson->custom && lesson_iscorrect($pageid, $answer->jumpto)) or ($lesson->custom && $answer->score > 0) ) { - if (!$useregexp) { // we are using 'normal analysis', which ignores case - if (preg_match('/^'.$expectedanswer.'$/i',$useranswer)) { - $ismatch = true; - } - } else { - if (preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$useranswer)) { - $ismatch = true; - } - } - if ($ismatch == true) { - $correctanswer = true; - } - } else { - if (!$useregexp) { //we are using 'normal analysis' - // see if user typed in any of the wrong answers; don't worry about case - if (preg_match('/^'.$expectedanswer.'$/i',$useranswer)) { - $ismatch = true; - } - } else { // we are using regular expressions analysis - $startcode = substr($expectedanswer,0,2); - switch ($startcode){ - //1- check for absence of required string in $useranswer (coded by initial '--') - case "--": - $expectedanswer = substr($expectedanswer,2); - if (!preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$useranswer)) { - $ismatch = true; - } - break; - //2- check for code for marking wrong strings (coded by initial '++') - case "++": - $expectedanswer=substr($expectedanswer,2); - $markit = true; - //check for one or several matches - if (preg_match_all('/'.$expectedanswer.'/'.$ignorecase,$useranswer, $matches)) { - $ismatch = true; - $nb = count($matches[0]); - $original = array(); - $marked = array(); - $fontStart = ''; - $fontEnd = ''; - for ($i = 0; $i < $nb; $i++) { - array_push($original,$matches[0][$i]); - array_push($marked,$fontStart.$matches[0][$i].$fontEnd); - } - $useranswer = str_replace($original, $marked, $useranswer); - } - break; - //3- check for wrong answers belonging neither to -- nor to ++ categories - default: - if (preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$useranswer, $matches)) { - $ismatch = true; - } - break; - } - $correctanswer = false; - } - } - if ($ismatch) { - $newpageid = $answer->jumpto; - if (trim(strip_tags($answer->response))) { - $response = $answer->response; - } - $answerid = $answer->id; - break; // quit answer analysis immediately after a match has been found - } - } - $studentanswer = $useranswer; - break; - - case LESSON_TRUEFALSE : - if (empty($_POST['answerid'])) { - $noanswer = true; - break; - } - $answerid = required_param('answerid', PARAM_INT); - if (!$answer = $DB->get_record("lesson_answers", array("id" => $answerid))) { - print_error("Continue: answer record not found"); - } - if (lesson_iscorrect($pageid, $answer->jumpto)) { - $correctanswer = true; - } - if ($lesson->custom) { - if ($answer->score > 0) { - $correctanswer = true; - } else { - $correctanswer = false; - } - } - $newpageid = $answer->jumpto; - $response = trim($answer->response); - $studentanswer = $answer->answer; - break; - - case LESSON_MULTICHOICE : - if ($page->qoption) { - // MULTIANSWER allowed, user's answer is an array - if (isset($_POST['answer'])) { - $useranswers = $_POST['answer']; - foreach ($useranswers as $key => $useranswer) { - $useranswers[$key] = clean_param($useranswer, PARAM_INT); - } - } else { - $noanswer = true; - break; - } - // get what the user answered - $userresponse = implode(",", $useranswers); - // get the answers in a set order, the id order - if (!$answers = $DB->get_records("lesson_answers", array("pageid" => $pageid), "id")) { - print_error("Continue: No answers found"); - } - $ncorrect = 0; - $nhits = 0; - $correctresponse = ''; - $wrongresponse = ''; - $correctanswerid = 0; - $wronganswerid = 0; - // store student's answers for displaying on feedback page - foreach ($answers as $answer) { - foreach ($useranswers as $key => $answerid) { - if ($answerid == $answer->id) { - $studentanswer .= '
'.$answer->answer; - } - } - } - // this is for custom scores. If score on answer is positive, it is correct - if ($lesson->custom) { - $ncorrect = 0; - $nhits = 0; - foreach ($answers as $answer) { - if ($answer->score > 0) { - $ncorrect++; - - foreach ($useranswers as $key => $answerid) { - if ($answerid == $answer->id) { - $nhits++; - } - } - // save the first jumpto page id, may be needed!... - if (!isset($correctpageid)) { - // leave in its "raw" state - will converted into a proper page id later - $correctpageid = $answer->jumpto; - } - // save the answer id for scoring - if ($correctanswerid == 0) { - $correctanswerid = $answer->id; - } - // ...also save any response from the correct answers... - if (trim(strip_tags($answer->response))) { - $correctresponse = $answer->response; - } - } else { - // save the first jumpto page id, may be needed!... - if (!isset($wrongpageid)) { - // leave in its "raw" state - will converted into a proper page id later - $wrongpageid = $answer->jumpto; - } - // save the answer id for scoring - if ($wronganswerid == 0) { - $wronganswerid = $answer->id; - } - // ...and from the incorrect ones, don't know which to use at this stage - if (trim(strip_tags($answer->response))) { - $wrongresponse = $answer->response; - } - } - } - } else { - foreach ($answers as $answer) { - if (lesson_iscorrect($pageid, $answer->jumpto)) { - $ncorrect++; - foreach ($useranswers as $key => $answerid) { - if ($answerid == $answer->id) { - $nhits++; - } - } - // save the first jumpto page id, may be needed!... - if (!isset($correctpageid)) { - // leave in its "raw" state - will converted into a proper page id later - $correctpageid = $answer->jumpto; - } - // save the answer id for scoring - if ($correctanswerid == 0) { - $correctanswerid = $answer->id; - } - // ...also save any response from the correct answers... - if (trim(strip_tags($answer->response))) { - $correctresponse = $answer->response; - } - } else { - // save the first jumpto page id, may be needed!... - if (!isset($wrongpageid)) { - // leave in its "raw" state - will converted into a proper page id later - $wrongpageid = $answer->jumpto; - } - // save the answer id for scoring - if ($wronganswerid == 0) { - $wronganswerid = $answer->id; - } - // ...and from the incorrect ones, don't know which to use at this stage - if (trim(strip_tags($answer->response))) { - $wrongresponse = $answer->response; - } - } - } - } - if ((count($useranswers) == $ncorrect) and ($nhits == $ncorrect)) { - $correctanswer = true; - $response = $correctresponse; - $newpageid = $correctpageid; - $answerid = $correctanswerid; - } else { - $response = $wrongresponse; - $newpageid = $wrongpageid; - $answerid = $wronganswerid; - } - } else { - // only one answer allowed - if (empty($_POST['answerid'])) { - $noanswer = true; - break; - } - $answerid = required_param('answerid', PARAM_INT); - if (!$answer = $DB->get_record("lesson_answers", array("id" => $answerid))) { - print_error("Continue: answer record not found"); - } - if (lesson_iscorrect($pageid, $answer->jumpto)) { - $correctanswer = true; - } - if ($lesson->custom) { - if ($answer->score > 0) { - $correctanswer = true; - } else { - $correctanswer = false; - } - } - $newpageid = $answer->jumpto; - $response = trim($answer->response); - $studentanswer = $answer->answer; - } - break; - case LESSON_MATCHING : - if (isset($_POST['response']) && is_array($_POST['response'])) { // only arrays should be submitted - $response = array(); - foreach ($_POST['response'] as $key => $value) { - $response[$key] = $value; - } - } else { - $noanswer = true; - break; - } - - if (!$answers = $DB->get_records("lesson_answers", array("pageid" => $pageid), "id")) { - print_error("Continue: No answers found"); - } - - $ncorrect = 0; - $i = 0; - foreach ($answers as $answer) { - if ($i == 0 || $i == 1) { - // ignore first two answers, they are correct response - // and wrong response - $i++; - continue; - } - if ($answer->response == $response[$answer->id]) { - $ncorrect++; - } - if ($i == 2) { - $correctpageid = $answer->jumpto; - $correctanswerid = $answer->id; - } - if ($i == 3) { - $wrongpageid = $answer->jumpto; - $wronganswerid = $answer->id; - } - $i++; - } - // get he users exact responses for record keeping - $userresponse = array(); - foreach ($response as $key => $value) { - foreach($answers as $answer) { - if ($value == $answer->response) { - $userresponse[] = $answer->id; - } - } - $studentanswer .= '
'.$answers[$key]->answer.' = '.$value; - } - $userresponse = implode(",", $userresponse); - - $response = ''; - if ($ncorrect == count($answers)-2) { // dont count correct/wrong responses in the total. - foreach ($answers as $answer) { - if ($answer->response == NULL && $answer->answer != NULL) { - $response = $answer->answer; - break; - } - } - if (isset($correctpageid)) { - $newpageid = $correctpageid; - } - if (isset($correctanswerid)) { - $answerid = $correctanswerid; - } - $correctanswer = true; - } else { - $t = 0; - foreach ($answers as $answer) { - if ($answer->response == NULL && $answer->answer != NULL) { - if ($t == 1) { - $response = $answer->answer; - break; - } - $t++; - } - } - $newpageid = $wrongpageid; - $answerid = $wronganswerid; - } - break; - - case LESSON_NUMERICAL : - // set defaults - $response = ''; - $newpageid = 0; - - if (isset($_POST['answer'])) { - $useranswer = (float) optional_param('answer', 0, PARAM_RAW); // just doing default PARAM_RAW, not doing PARAM_INT because it could be a float - } else { - $noanswer = true; - break; - } - $studentanswer = $userresponse = $useranswer; - if (!$answers = $DB->get_records("lesson_answers", array("pageid" => $pageid), "id")) { - print_error("Continue: No answers found"); - } - foreach ($answers as $answer) { - if (strpos($answer->answer, ':')) { - // there's a pairs of values - list($min, $max) = explode(':', $answer->answer); - $minimum = (float) $min; - $maximum = (float) $max; - } else { - // there's only one value - $minimum = (float) $answer->answer; - $maximum = $minimum; - } - if (($useranswer >= $minimum) and ($useranswer <= $maximum)) { - $newpageid = $answer->jumpto; - $response = trim($answer->response); - if (lesson_iscorrect($pageid, $newpageid)) { - $correctanswer = true; - } - if ($lesson->custom) { - if ($answer->score > 0) { - $correctanswer = true; - } else { - $correctanswer = false; - } - } - $answerid = $answer->id; - break; - } - } - break; - - case LESSON_BRANCHTABLE: - $noanswer = false; - $newpageid = optional_param('jumpto', NULL, PARAM_INT); - // going to insert into lesson_branch - if ($newpageid == LESSON_RANDOMBRANCH) { - $branchflag = 1; - } else { - $branchflag = 0; - } - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if ($grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid AND userid = :userid", - $params, "grade DESC")) { - $retries = count($grades); - } else { - $retries = 0; - } - $branch = new stdClass; - $branch->lessonid = $lesson->id; - $branch->userid = $USER->id; - $branch->pageid = $pageid; - $branch->retry = $retries; - $branch->flag = $branchflag; - $branch->timeseen = time(); - - $DB->insert_record("lesson_branch", $branch); - - // this is called when jumping to random from a branch table - if($newpageid == LESSON_UNSEENBRANCHPAGE) { - if (has_capability('mod/lesson:manage', $context)) { - $newpageid = LESSON_NEXTPAGE; - } else { - $newpageid = lesson_unseen_question_jump($lesson->id, $USER->id, $pageid); // this may return 0 - } - } - // convert jumpto page into a proper page id - if ($newpageid == 0) { - $newpageid = $pageid; - } elseif ($newpageid == LESSON_NEXTPAGE) { - if (!$newpageid = $page->nextpageid) { - // no nextpage go to end of lesson - $newpageid = LESSON_EOL; - } - } elseif ($newpageid == LESSON_PREVIOUSPAGE) { - $newpageid = $page->prevpageid; - } elseif ($newpageid == LESSON_RANDOMPAGE) { - $newpageid = lesson_random_question_jump($lesson->id, $pageid); - } elseif ($newpageid == LESSON_RANDOMBRANCH) { - $newpageid = lesson_unseen_branch_jump($lesson->id, $USER->id); - } - // no need to record anything in lesson_attempts - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=$newpageid"); - break; - - } - - $attemptsremaining = 0; - $maxattemptsreached = 0; - $nodefaultresponse = false; // Flag for redirecting when default feedback is turned off - - if ($noanswer) { - $newpageid = $pageid; // display same page again - $feedback = get_string('noanswer', 'lesson'); - } else { - $nretakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - if (!has_capability('mod/lesson:manage', $context)) { - // record student's attempt - $attempt = new stdClass; - $attempt->lessonid = $lesson->id; - $attempt->pageid = $pageid; - $attempt->userid = $USER->id; - $attempt->answerid = $answerid; - $attempt->retry = $nretakes; - $attempt->correct = $correctanswer; - if(isset($userresponse)) { - $attempt->useranswer = $userresponse; - } - - $attempt->timeseen = time(); - // if allow modattempts, then update the old attempt record, otherwise, insert new answer record - if (isset($USER->modattempts[$lesson->id])) { - $attempt->retry = $nretakes - 1; // they are going through on review, $nretakes will be too high - } - $newattemptid = $DB->insert_record("lesson_attempts", $attempt); - // "number of attempts remaining" message if $lesson->maxattempts > 1 - // displaying of message(s) is at the end of page for more ergonomic display - if (!$correctanswer and ($newpageid == 0)) { - // wrong answer and student is stuck on this page - check how many attempts - // the student has had at this page/question - $nattempts = $DB->count_records("lesson_attempts", array("pageid"=>$pageid, "userid"=>$USER->id), - "retry", $nretakes); - - // retreive the number of attempts left counter for displaying at bottom of feedback page - if ($nattempts >= $lesson->maxattempts) { - if ($lesson->maxattempts > 1) { // don't bother with message if only one attempt - $maxattemptsreached = 1; - } - $newpageid = LESSON_NEXTPAGE; - } else if ($lesson->maxattempts > 1) { // don't bother with message if only one attempt - $attemptsremaining = $lesson->maxattempts - $nattempts; - } - } - } - // TODO: merge this code with the jump code below. Convert jumpto page into a proper page id - if ($newpageid == 0) { - $newpageid = $pageid; - } elseif ($newpageid == LESSON_NEXTPAGE) { - if ($lesson->nextpagedefault) { - // in Flash Card mode... - // ... first get the page ids (lessonid the 5th param is needed to make $DB->get_records play) - $allpages = $DB->get_records("lesson_pages", array("lessonid" => $lesson->id), "id", "id,lessonid,qtype"); - shuffle ($allpages); - $found = false; - if ($lesson->nextpagedefault == LESSON_UNSEENPAGE) { - foreach ($allpages as $thispage) { - if (!$DB->count_records("lesson_attempts", array("pageid"=>$thispage->id, "userid"=>$USER->id, "retry"=>$nretakes))) { - $found = true; - break; - } - } - } elseif ($lesson->nextpagedefault == LESSON_UNANSWEREDPAGE) { - foreach ($allpages as $thispage) { - if ($thispage->qtype == LESSON_ESSAY) { - if (!$DB->count_records("lesson_attempts", array('pageid'=>$thispage->id, 'userid'=>$USER->id, 'retry'=>$nretakes))) { - $found = true; - break; - } - } else { - if (!$DB->count_records("lesson_attempts", array('pageid'=>$thispage->id, 'userid'=>$USER->id, 'correct'=>1, 'retry'=>$nretakes))) { - $found = true; - break; - } - } - } - } - if ($found) { - $newpageid = $thispage->id; - if ($lesson->maxpages) { - // check number of pages viewed (in the lesson) - if ($DB->count_records("lesson_attempts", array("lessonid"=>$lesson->id, "userid"=>$USER->id, - "retry"=>$nretakes)) >= $lesson->maxpages) { - $newpageid = LESSON_EOL; - } - } - } else { - $newpageid = LESSON_EOL; - } - } elseif (!$newpageid = $page->nextpageid) { - // no nextpage go to end of lesson - $newpageid = LESSON_EOL; - } - } - - // Determine default feedback if necessary - if (empty($response)) { - if (!$lesson->feedback and !$noanswer and !($lesson->review and !$correctanswer and !$isessayquestion)) { - // These conditions have been met: - // 1. The lesson manager has not supplied feedback to the student - // 2. Not displaying default feedback - // 3. The user did provide an answer - // 4. We are not reviewing with an incorrect answer (and not reviewing an essay question) - - $nodefaultresponse = true; // This will cause a redirect below - } else if ($isessayquestion) { - $response = get_string('defaultessayresponse', 'lesson'); - } else if ($correctanswer) { - $response = get_string('thatsthecorrectanswer', 'lesson'); - } else { - $response = get_string('thatsthewronganswer', 'lesson'); - } - } - - // display response (if there is one - there should be!) - // display: lesson title, page title, question text, student's answer(s) before feedback message - - if ($response) { - //optionally display question page title - //if ($title = $DB->get_field("lesson_pages", "title", array("id" => $pageid))) { - // print_heading($title); - //} - if ($lesson->review and !$correctanswer and !$isessayquestion) { - $nretakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - $qattempts = $DB->count_records("lesson_attempts", array("userid"=>$USER->id, "retry"=>$nretakes, "pageid"=>$pageid)); - if ($qattempts == 1) { - $feedback = get_string("firstwrong", "lesson"); - } else { - $feedback = get_string("secondpluswrong", "lesson"); - } - } else { - if ($correctanswer) { - $class = 'response correct'; //CSS over-ride this if they exist (!important) - } else if ($isessayquestion) { - $class = 'response'; - } else { - $class = 'response incorrect'; - } - $options = new stdClass; - $options->noclean = true; - $options->para = true; - $feedback = $OUTPUT->box(format_text($page->contents, FORMAT_MOODLE, $options), 'generalbox boxaligncenter'); - $feedback .= ''.get_string("youranswer", "lesson").' : '.format_text($studentanswer, FORMAT_MOODLE, $options). - "
".format_text($response, FORMAT_MOODLE, $options).'
'; - } - } - } - - // TODO: merge with the jump code above. This is where some jump numbers are interpreted - if (isset($USER->modattempts[$lesson->id])) { - // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time - if ($USER->modattempts[$lesson->id] == $pageid) { // remember, this session variable holds the pageid of the last page that the user saw - $newpageid = LESSON_EOL; - } else { - $nretakes--; // make sure we are looking at the right try. - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $nretakes); - $attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen", "id, pageid"); - $found = false; - $temppageid = 0; - foreach($attempts as $attempt) { - if ($found && $temppageid != $attempt->pageid) { // now try to find the next page, make sure next few attempts do no belong to current page - $newpageid = $attempt->pageid; - break; - } - if ($attempt->pageid == $pageid) { - $found = true; // if found current page - $temppageid = $attempt->pageid; - } - } - } - } elseif ($newpageid != LESSON_CLUSTERJUMP && $pageid != 0 && $newpageid > 0) { // going to check to see if the page that the user is going to view next, is a cluster page. If so, dont display, go into the cluster. The $newpageid > 0 is used to filter out all of the negative code jumps. - if (!$page = $DB->get_record("lesson_pages", array("id" => $newpageid))) { - print_error("Error: could not find page"); - } - if ($page->qtype == LESSON_CLUSTER) { - $newpageid = lesson_cluster_jump($lesson->id, $USER->id, $page->id); - } elseif ($page->qtype == LESSON_ENDOFCLUSTER) { - $jump = $DB->get_field("lesson_answers", "jumpto", array("pageid" => $page->id, "lessonid" => $lesson->id)); - if ($jump == LESSON_NEXTPAGE) { - if ($page->nextpageid == 0) { - $newpageid = LESSON_EOL; - } else { - $newpageid = $page->nextpageid; - } - } else { - $newpageid = $jump; - } - } - } elseif ($newpageid == LESSON_UNSEENBRANCHPAGE) { - if (has_capability('mod/lesson:manage', $context)) { - if ($page->nextpageid == 0) { - $newpageid = LESSON_EOL; - } else { - $newpageid = $page->nextpageid; - } - } else { - $newpageid = lesson_unseen_question_jump($lesson->id, $USER->id, $pageid); - } - } elseif ($newpageid == LESSON_PREVIOUSPAGE) { - $newpageid = $page->prevpageid; - } elseif ($newpageid == LESSON_RANDOMPAGE) { - $newpageid = lesson_random_question_jump($lesson->id, $pageid); - } elseif ($newpageid == LESSON_CLUSTERJUMP) { - if (has_capability('mod/lesson:manage', $context)) { - if ($page->nextpageid == 0) { // if teacher, go to next page - $newpageid = LESSON_EOL; - } else { - $newpageid = $page->nextpageid; - } - } else { - $newpageid = lesson_cluster_jump($lesson->id, $USER->id, $pageid); - } - } - - if ($nodefaultresponse) { - // Don't display feedback - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=$newpageid"); - } - -/// Set Messages - - // This is the warning msg for teachers to inform them that cluster and unseen does not work while logged in as a teacher - if(has_capability('mod/lesson:manage', $context) and lesson_display_teacher_warning($lesson->id)) { - $warningvars->cluster = get_string("clusterjump", "lesson"); - $warningvars->unseen = get_string("unseenpageinbranch", "lesson"); - lesson_set_message(get_string("teacherjumpwarning", "lesson", $warningvars)); - } - // Inform teacher that s/he will not see the timer - if ($lesson->timed and has_capability('mod/lesson:manage', $context)) { - lesson_set_message(get_string("teachertimerwarning", "lesson")); - } - // Report attempts remaining - if ($attemptsremaining != 0) { - lesson_set_message(get_string('attemptsremaining', 'lesson', $attemptsremaining)); - } - // Report if max attempts reached - if ($maxattemptsreached != 0) { - lesson_set_message('('.get_string("maximumnumberofattemptsreached", "lesson").')'); - } - - $PAGE->set_url('mod/lesson/view.php', array('id' => $cm->id, 'pageid' => $page->id)); - $PAGE->set_subpage($page->id); - -/// Print the header, heading and tabs - lesson_add_pretend_blocks($PAGE, $cm, $lesson, $timer); - lesson_print_header($cm, $course, $lesson, 'view', true, $page->id); - - include(dirname(__FILE__).'/continue.html'); - diff --git a/mod/lesson/action/delete.php b/mod/lesson/action/delete.php deleted file mode 100644 index 2ba5c4d1c7..0000000000 --- a/mod/lesson/action/delete.php +++ /dev/null @@ -1,58 +0,0 @@ -get_record("lesson_pages", array("id" => $pageid))) { - print_error("Delete: page record not found"); - } - - // first delete all the associated records... - $DB->delete_records("lesson_attempts", array("pageid" => $pageid)); - // ...now delete the answers... - $DB->delete_records("lesson_answers", array("pageid" => $pageid)); - // ..and the page itself - $DB->delete_records("lesson_pages", array("id" => $pageid)); - - // repair the hole in the linkage - if (!$thispage->prevpageid AND !$thispage->nextpageid) { - //This is the only page, no repair needed - } elseif (!$thispage->prevpageid) { - // this is the first page... - if (!$page = $DB->get_record("lesson_pages", array("id" => $thispage->nextpageid))) { - print_error("Delete: next page not found"); - } - if (!$DB->set_field("lesson_pages", "prevpageid", 0, array("id" => $page->id))) { - print_error("Delete: unable to set prevpage link"); - } - } elseif (!$thispage->nextpageid) { - // this is the last page... - if (!$page = $DB->get_record("lesson_pages", array("id" => $thispage->prevpageid))) { - print_error("Delete: prev page not found"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", 0, array("id" => $page->id))) { - print_error("Delete: unable to set nextpage link"); - } - } else { - // page is in the middle... - if (!$prevpage = $DB->get_record("lesson_pages", array("id" => $thispage->prevpageid))) { - print_error("Delete: prev page not found"); - } - if (!$nextpage = $DB->get_record("lesson_pages", array("id" => $thispage->nextpageid))) { - print_error("Delete: next page not found"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", $nextpage->id, array("id" => $prevpage->id))) { - print_error("Delete: unable to set next link"); - } - if (!$DB->set_field("lesson_pages", "prevpageid", $prevpage->id, array("id" => $nextpage->id))) { - print_error("Delete: unable to set prev link"); - } - } - lesson_set_message(get_string('deletedpage', 'lesson').': '.format_string($thispage->title, true), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - diff --git a/mod/lesson/action/editpage.php b/mod/lesson/action/editpage.php deleted file mode 100644 index 36379e38a7..0000000000 --- a/mod/lesson/action/editpage.php +++ /dev/null @@ -1,473 +0,0 @@ -get_record("lesson_pages", array("id" => $pageid))) { - print_error('cannotfindpages', 'lesson'); - } - - $page->qtype = optional_param('qtype', $page->qtype, PARAM_INT); - - // set of jump array - $jump = array(); - $jump[0] = get_string("thispage", "lesson"); - $jump[LESSON_NEXTPAGE] = get_string("nextpage", "lesson"); - $jump[LESSON_PREVIOUSPAGE] = get_string("previouspage", "lesson"); - if(lesson_display_branch_jumps($lesson->id, $page->id)) { - $jump[LESSON_UNSEENBRANCHPAGE] = get_string("unseenpageinbranch", "lesson"); - $jump[LESSON_RANDOMPAGE] = get_string("randompageinbranch", "lesson"); - } - if ($page->qtype == LESSON_ENDOFBRANCH || $page->qtype == LESSON_BRANCHTABLE) { - $jump[LESSON_RANDOMBRANCH] = get_string("randombranch", "lesson"); - } - if(lesson_display_cluster_jump($lesson->id, $page->id) && $page->qtype != LESSON_BRANCHTABLE && $page->qtype != LESSON_ENDOFCLUSTER) { - $jump[LESSON_CLUSTERJUMP] = get_string("clusterjump", "lesson"); - } - $jump[LESSON_EOL] = get_string("endoflesson", "lesson"); - if (!$apageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0))) { - print_error('cannotfindfirstpage', 'lesson'); - } - while (true) { - if ($apageid) { - if (!$apage = $DB->get_record("lesson_pages", array("id" => $apageid))) { - print_error('cannotfindpages', 'lesson'); - } - // removed != LESSON_ENDOFBRANCH... - if (trim($page->title)) { // ...nor nuffin pages - $jump[$apageid] = strip_tags(format_string($apage->title,true)); - } - $apageid = $apage->nextpageid; - } else { - // last page reached - break; - } - } - // give teacher a proforma - ?> -
-
- - - - - - -
- qtype) { - case LESSON_MULTICHOICE : - echo ''.get_string("questiontype", "lesson").": \n"; - echo $OUTPUT->help_icon(moodle_help_icon::make("questiontypes", get_string("questiontype", "lesson"), "lesson"))."
"; - lesson_qtype_menu($LESSON_QUESTION_TYPE, $page->qtype, - "lesson.php?id=$cm->id&action=editpage&pageid=$page->id", - "getElementById('editpage').redisplay.value=1;getElementById('editpage').submit();"); - echo "

\n"; - if ($page->qoption) { - echo ""; - } else { - echo ""; - } - echo $OUTPUT->help_icon(moodle_help_icon::make("questionoption", get_string("questionoption", "lesson"), "lesson")); - echo "

\n"; - break; - case LESSON_SHORTANSWER : - echo ''.get_string("questiontype", "lesson").": \n"; - echo $OUTPUT->help_icon(moodle_help_icon::make("questiontypes", get_string("questiontype", "lesson"), "lesson"))."
"; - lesson_qtype_menu($LESSON_QUESTION_TYPE, $page->qtype, - "lesson.php?id=$cm->id&action=editpage&pageid=$page->id", - "getElementById('editpage').redisplay.value=1;getElementById('editpage').submit();"); - echo "

\n"; - if ($page->qoption) { - echo ""; - } else { - echo ""; - } - echo $OUTPUT->help_icon(moodle_help_icon::make("questionoption", get_string("questionoption", "lesson"), "lesson")); - echo "

\n"; - break; - case LESSON_TRUEFALSE : - case LESSON_ESSAY : - case LESSON_MATCHING : - case LESSON_NUMERICAL : - echo ''.get_string("questiontype", "lesson").": \n"; - echo $OUTPUT->help_icon(moodle_help_icon::make("questiontypes", get_string("questiontype", "lesson"), "lesson"))."
"; - lesson_qtype_menu($LESSON_QUESTION_TYPE, $page->qtype, - "lesson.php?id=$cm->id&action=editpage&pageid=$page->id", - "getElementById('editpage').redisplay.value=1;getElementById('editpage').submit();"); - break; - } - ?> - - - - - \n"; - $n = 0; - switch ($page->qtype) { - case LESSON_BRANCHTABLE : - echo "qtype\" />\n"; - echo "\n"; - echo "\n"; - // get the answers in a set order, the id order - - if ($answers = $DB->get_records("lesson_answers", array("pageid" => $page->id), "id")) { - foreach ($answers as $answer) { - $flags = intval($answer->flags); // force into an integer - $nplus1 = $n + 1; - echo "id\" />\n"; - switch ($page->qtype) { - case LESSON_MATCHING: - if ($n == 0) { - echo "\n"; - echo "\n"; - break; - case LESSON_TRUEFALSE: - case LESSON_MULTICHOICE: - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - echo "\n"; - echo "\n"; - break; - case LESSON_BRANCHTABLE: - echo "\n"; - break; - } - switch ($page->qtype) { - case LESSON_MATCHING : - if ($n == 2) { - echo "\n"; - } - if ($n == 3) { - echo "\n"; - } - //echo "\n"; - break; - case LESSON_ESSAY : - echo "\n"; - break; - case LESSON_TRUEFALSE: - case LESSON_MULTICHOICE: - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - echo "\n"; - break; - case LESSON_BRANCHTABLE: - case LESSON_CLUSTER: - case LESSON_ENDOFCLUSTER: - case LESSON_ENDOFBRANCH: - echo "\n"; - break; - } - $n++; - if ($page->qtype == LESSON_ESSAY) { - break; // only one answer for essays - } - } - } - if ($page->qtype != LESSON_ENDOFBRANCH && $page->qtype != LESSON_CLUSTER && $page->qtype != LESSON_ENDOFCLUSTER) { - if ($page->qtype == LESSON_MATCHING) { - $maxanswers = $lesson->maxanswers + 2; - } else { - $maxanswers = $lesson->maxanswers; - } - for ($i = $n; $i < $maxanswers; $i++) { - if ($page->qtype == LESSON_TRUEFALSE && $i > 1) { - break; // stop printing answers... only need two for true/false - } - $iplus1 = $i + 1; - echo "\n"; - switch ($page->qtype) { - case LESSON_MATCHING: - $icorrected = $i - 1; - echo "\n"; - echo "\n"; - break; - case LESSON_TRUEFALSE: - case LESSON_MULTICHOICE: - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - echo "\n"; - echo "\n"; - break; - case LESSON_BRANCHTABLE: - echo "\n"; - break; - } - switch ($page->qtype) { - case LESSON_ESSAY : - if ($i < 1) { - echo "\n"; - } - break; - case LESSON_MATCHING : - if ($i == 2) { - echo "\n"; - } - if ($i == 3) { - echo "\n"; - } - - break; - case LESSON_TRUEFALSE: - case LESSON_MULTICHOICE: - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - echo "\n"; - break; - case LESSON_BRANCHTABLE : - echo "\n"; - break; - } - } - } - // close table and form - ?> -

-
"; - echo get_string("pagecontents", "lesson").":
\n"; - print_textarea($usehtmleditor, 25, 70, 630, 400, "contents", $page->contents); - echo "
\n"; - echo "
"; - if ($page->layout) { - echo ""; - } else { - echo ""; - } - echo get_string("arrangebuttonshorizontally", "lesson")."\n"; - echo "
"; - if ($page->display) { - echo ""; - } else { - echo ""; - } - echo get_string("displayinleftmenu", "lesson")."\n"; - echo "
".get_string("branchtable", "lesson")." \n"; - break; - case LESSON_CLUSTER : - echo "qtype\" />\n"; - echo "
".get_string("clustertitle", "lesson")." \n"; - break; - case LESSON_ENDOFCLUSTER : - echo "qtype\" />\n"; - echo "
".get_string("endofclustertitle", "lesson")." \n"; - break; - case LESSON_ENDOFBRANCH : - echo "qtype\" />\n"; - echo "
".get_string("endofbranch", "lesson")." \n"; - break; - default : - echo "
"; - break; - } - - echo "
\n"; - if ($flags & LESSON_ANSWER_EDITOR) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$n]", $answer->answer); - } else { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$n]", $answer->answer); - } - } elseif ($n == 1) { - echo "
\n"; - if ($flags & LESSON_ANSWER_EDITOR) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$n]", $answer->answer); - } else { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$n]", $answer->answer); - } - } else { - $ncorrected = $n - 1; - echo "
\n"; - if ($flags & LESSON_ANSWER_EDITOR) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$n]", $answer->answer); - } else { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$n]", $answer->answer); - } - echo "
\n"; - if ($flags & LESSON_RESPONSE_EDITOR) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "response[$n]", $answer->response); - } else { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 6, 70, 630, 300, "response[$n]", $answer->response); - } - } - echo "
\n"; - if ($flags & LESSON_ANSWER_EDITOR and $page->qtype != LESSON_SHORTANSWER and $page->qtype != LESSON_NUMERICAL) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$n]", $answer->answer); - } else { - if ($page->qtype != LESSON_SHORTANSWER and $page->qtype != LESSON_NUMERICAL) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 6, 70, 630, 300, "answer[$n]", $answer->answer); - } else { - echo "
\n"; - print_textarea(false, 1, 70, 630, 300, "answer[$n]", $answer->answer); - } - } - echo "
\n"; - if ($flags & LESSON_RESPONSE_EDITOR) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "response[$n]", $answer->response); - } else { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 6, 70, 630, 300, "response[$n]", $answer->response); - } - echo "
\n"; - if ($flags & LESSON_ANSWER_EDITOR) { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$n]", $answer->answer); - } else { - echo " [: ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 10, 70, 630, 300, "answer[$n]", $answer->answer); - } - echo "
".get_string("correctanswerjump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$n]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) - echo get_string("correctanswerscore", "lesson").": score\" size=\"5\" />"; - echo "
".get_string("wronganswerjump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$n]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) - echo get_string("wronganswerscore", "lesson").": score\" size=\"5\" />"; - echo "
".get_string("jump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$n]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - echo get_string("score", "lesson").": score\" size=\"5\" />"; - } - echo "
".get_string("jump", "lesson")." $nplus1: \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$n]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - echo get_string("score", "lesson")." $nplus1: score\" size=\"5\" />"; - } - echo "
".get_string("jump", "lesson")." $nplus1: \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$n]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - echo "
".get_string("answer", "lesson")." $icorrected:\n"; - echo " [".get_string("useeditor", "lesson").": ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 10, 70, 630, 300, "answer[$i]"); - echo "
".get_string("matchesanswer", "lesson")." $icorrected:\n"; - echo " [".get_string("useeditor", "lesson").": ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 10, 70, 630, 300, "response[$i]"); - echo "
".get_string("answer", "lesson")." $iplus1:\n"; - if ($page->qtype != LESSON_SHORTANSWER and $page->qtype != LESSON_NUMERICAL) { - echo " [".get_string("useeditor", "lesson").": ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 10, 70, 630, 300, "answer[$i]"); - } else { - echo "
\n"; - print_textarea(false, 1, 70, 630, 300, "answer[$i]"); - } - echo "
".get_string("response", "lesson")." $iplus1:\n"; - echo " [".get_string("useeditor", "lesson").": ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 10, 70, 630, 300, "response[$i]"); - echo "
".get_string("description", "lesson")." $iplus1:\n"; - echo " [".get_string("useeditor", "lesson").": ". - ""; - echo $OUTPUT->help_icon(moodle_help_icon::make("useeditor", get_string("useeditor", "lesson"), "lesson")); - echo "]
\n"; - print_textarea(false, 10, 70, 630, 300, "answer[$i]"); - echo "
".get_string("jump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - echo get_string("score", "lesson").": "; - } - echo "
".get_string("correctanswerjump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if ($lesson->custom) { - echo get_string("correctanswerscore", "lesson").": score\" size=\"5\" />"; - } - echo "
".get_string("wronganswerjump", "lesson").": \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", $answer->jumpto, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if ($lesson->custom) { - echo get_string("wronganswerscore", "lesson").": score\" size=\"5\" />"; - } - echo "
".get_string("jump", "lesson")." $iplus1: \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - if($lesson->custom) { - echo get_string("score", "lesson")." $iplus1: "; - } - echo "
".get_string("jump", "lesson")." $iplus1: \n"; - echo $OUTPUT->select(html_select::make($jump, "jumpto[$i]", 0, false)); - echo $OUTPUT->help_icon(moodle_help_icon::make("jumpto", get_string("jump", "lesson"), "lesson")); - echo "

- " - onclick="getElementById('editpage').redisplay.value=1;getElementById('editpage').submit();" /> - " /> - " /> -
-
-
diff --git a/mod/lesson/action/insertpage.php b/mod/lesson/action/insertpage.php deleted file mode 100644 index 6fa694ebed..0000000000 --- a/mod/lesson/action/insertpage.php +++ /dev/null @@ -1,167 +0,0 @@ -wwwroot/mod/lesson/edit.php?id=$cm->id"); - } - - $timenow = time(); - - $form = data_submitted(); - $newpage = new stdClass; - $newanswer = new stdClass; - if ($form->pageid) { - // the new page is not the first page - if (!$page = $DB->get_record("lesson_pages", array("id" => $form->pageid))) { - print_error('cannotfindpages', 'lesson'); - } - $newpage->lessonid = clean_param($lesson->id, PARAM_INT); - $newpage->prevpageid = clean_param($form->pageid, PARAM_INT); - $newpage->nextpageid = clean_param($page->nextpageid, PARAM_INT); - $newpage->timecreated = $timenow; - $newpage->qtype = $form->qtype; - if (isset($form->qoption)) { - $newpage->qoption = clean_param($form->qoption, PARAM_INT); - } else { - $newpage->qoption = 0; - } - if (isset($form->layout)) { - $newpage->layout = clean_param($form->layout, PARAM_INT); - } else { - $newpage->layout = 0; - } - if (isset($form->display)) { - $newpage->display = clean_param($form->display, PARAM_INT); - } else { - $newpage->display = 0; - } - $newpage->title = clean_param($form->title, PARAM_CLEANHTML); - $newpage->contents = trim($form->contents); - $newpage->title = $newpage->title; - $newpageid = $DB->insert_record("lesson_pages", $newpage); - // update the linked list (point the previous page to this new one) - $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $newpage->prevpageid)); - if ($page->nextpageid) { - // new page is not the last page - $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); - } - } else { - // new page is the first page - // get the existing (first) page (if any) - $params = array ("lessonid" => $lesson->id, "prevpageid" => 0); - if (!$page = $DB->get_record_select("lesson_pages", "lessonid = :lessonid AND prevpageid = :prevpageid", $params)) { - // there are no existing pages - $newpage->lessonid = $lesson->id; - $newpage->prevpageid = 0; // this is a first page - $newpage->nextpageid = 0; // this is the only page - $newpage->timecreated = $timenow; - $newpage->qtype = clean_param($form->qtype, PARAM_INT); - if (isset($form->qoption)) { - $newpage->qoption = clean_param($form->qoption, PARAM_INT); - } else { - $newpage->qoption = 0; - } - if (isset($form->layout)) { - $newpage->layout = clean_param($form->layout, PARAM_INT); - } else { - $newpage->layout = 0; - } - if (isset($form->display)) { - $newpage->display = clean_param($form->display, PARAM_INT); - } else { - $newpage->display = 0; - } - $newpage->title = clean_param($form->title, PARAM_CLEANHTML); - $newpage->contents = trim($form->contents); - $newpage->title = $newpage->title; - $newpageid = $DB->insert_record("lesson_pages", $newpage); - } else { - // there are existing pages put this at the start - $newpage->lessonid = $lesson->id; - $newpage->prevpageid = 0; // this is a first page - $newpage->nextpageid = $page->id; - $newpage->timecreated = $timenow; - $newpage->qtype = clean_param($form->qtype, PARAM_INT); - if (isset($form->qoption)) { - $newpage->qoption = clean_param($form->qoption, PARAM_INT); - } else { - $newpage->qoption = 0; - } - if (isset($form->layout)) { - $newpage->layout = clean_param($form->layout, PARAM_INT); - } else { - $newpage->layout = 0; - } - if (isset($form->display)) { - $newpage->display = clean_param($form->display, PARAM_INT); - } else { - $newpage->display = 0; - } - $newpage->title = clean_param($form->title, PARAM_CLEANHTML); - $newpage->contents = trim($form->contents); - $newpage->title = $newpage->title; - $newpageid = $DB->insert_record("lesson_pages", $newpage); - // update the linked list - $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $newpage->nextpageid)); - } - } - // now add the answers - if ($form->qtype == LESSON_ESSAY) { - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $newpageid; - $newanswer->timecreated = $timenow; - if (isset($form->jumpto[0])) { - $newanswer->jumpto = clean_param($form->jumpto[0], PARAM_INT); - } - if (isset($form->score[0])) { - $newanswer->score = clean_param($form->score[0], PARAM_INT); - } - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - } else { - if ($form->qtype == LESSON_MATCHING) { - // need to add two to offset correct response and wrong response - $lesson->maxanswers = $lesson->maxanswers + 2; - } - for ($i = 0; $i < $lesson->maxanswers; $i++) { - if (!empty($form->answer[$i]) and trim(strip_tags($form->answer[$i]))) { // strip_tags because the HTML editor adds


... - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $newpageid; - $newanswer->timecreated = $timenow; - $newanswer->answer = trim($form->answer[$i]); - if (isset($form->response[$i])) { - $newanswer->response = trim($form->response[$i]); - } - if (isset($form->jumpto[$i])) { - $newanswer->jumpto = clean_param($form->jumpto[$i], PARAM_INT); - } - if ($lesson->custom) { - if (isset($form->score[$i])) { - $newanswer->score = clean_param($form->score[$i], PARAM_INT); - } - } - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - } else { - if ($form->qtype == LESSON_MATCHING) { - if ($i < 2) { - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $newpageid; - $newanswer->timecreated = $timenow; - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - } - } else { - break; - } - } - } - } - - lesson_set_message(get_string('insertedpage', 'lesson').': '.format_string($newpage->title, true), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - diff --git a/mod/lesson/action/move.php b/mod/lesson/action/move.php deleted file mode 100644 index d90100e025..0000000000 --- a/mod/lesson/action/move.php +++ /dev/null @@ -1,40 +0,0 @@ -get_field("lesson_pages", "title", array("id" => $pageid)); - echo $OUTPUT->heading(get_string("moving", "lesson", format_string($title))); - - $params = array ("lessonid" => $lesson->id, "prevpageid" => 0); - if (!$page = $DB->get_record_select("lesson_pages", "lessonid = :lessonid AND prevpageid = :prevpageid", $params)) { - print_error('cannotfindfirstpage', 'lesson'); - } - - echo "

\n"; - echo "\n"; - while (true) { - if ($page->id != $pageid) { - if (!$title = trim(format_string($page->title))) { - $title = "<< ".get_string("notitle", "lesson")." >>"; - } - echo "\n"; - echo "\n"; - } - if ($page->nextpageid) { - if (!$page = $DB->get_record("lesson_pages", array("id" => $page->nextpageid))) { - print_error('cannotfindnextpage', 'lesson'); - } - } else { - // last page reached - break; - } - } - echo "
id&sesskey=".sesskey()."&action=moveit&pageid=$pageid&after=0\">". - get_string("movepagehere", "lesson")."
$title
id&sesskey=".sesskey()."&action=moveit&pageid=$pageid&after={$page->id}\">". - get_string("movepagehere", "lesson")."
\n"; - diff --git a/mod/lesson/action/moveit.php b/mod/lesson/action/moveit.php deleted file mode 100644 index 1c81fe7d97..0000000000 --- a/mod/lesson/action/moveit.php +++ /dev/null @@ -1,100 +0,0 @@ -get_record("lesson_pages", array("id" => $pageid))) { - print_error("Moveit: page not found"); - } - $after = required_param('after', PARAM_INT); // target page - - // first step. determine the new first page - // (this is done first as the current first page will be lost in the next step) - if (!$after) { - // the moved page is the new first page - $newfirstpageid = $pageid; - // reset $after so that is points to the last page - // (when the pages are in a ring this will in effect be the first page) - if ($page->nextpageid) { - if (!$after = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "nextpageid" => 0))) { - print_error("Moveit: last page id not found"); - } - } else { - // the page being moved is the last page, so the new last page will be - $after = $page->prevpageid; - } - } elseif (!$page->prevpageid) { - // the page to be moved was the first page, so the following page must be the new first page - $newfirstpageid = $page->nextpageid; - } else { - // the current first page remains the first page - if (!$newfirstpageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0))) { - print_error("Moveit: current first page id not found"); - } - } - // the rest is all unconditional... - - // second step. join pages into a ring - if (!$firstpageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0))) { - print_error("Moveit: firstpageid not found"); - } - if (!$lastpageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "nextpageid" => 0))) { - print_error("Moveit: lastpage not found"); - } - if (!$DB->set_field("lesson_pages", "prevpageid", $lastpageid, array("id" => $firstpageid))) { - print_error("Moveit: unable to update link"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", $firstpageid, array("id" => $lastpageid))) { - print_error("Moveit: unable to update link"); - } - - // third step. remove the page to be moved - if (!$prevpageid = $DB->get_field("lesson_pages", "prevpageid", array("id" => $pageid))) { - print_error("Moveit: prevpageid not found"); - } - if (!$nextpageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $pageid))) { - print_error("Moveit: nextpageid not found"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", $nextpageid, array("id" => $prevpageid))) { - print_error("Moveit: unable to update link"); - } - if (!$DB->set_field("lesson_pages", "prevpageid", $prevpageid, array("id" => $nextpageid))) { - print_error("Moveit: unable to update link"); - } - - // fourth step. insert page to be moved in new place... - if (!$nextpageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $after))) { - print_error("Movit: nextpageid not found"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", $pageid, array("id" => $after))) { - print_error("Moveit: unable to update link"); - } - if (!$DB->set_field("lesson_pages", "prevpageid", $pageid, array("id" => $nextpageid))) { - print_error("Moveit: unable to update link"); - } - // ...and set the links in the moved page - if (!$DB->set_field("lesson_pages", "prevpageid", $after, array("id" => $pageid))) { - print_error("Moveit: unable to update link"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", $nextpageid, array("id" => $pageid))) { - print_error("Moveit: unable to update link"); - } - - // fifth step. break the ring - if (!$newlastpageid = $DB->get_field("lesson_pages", "prevpageid", array("id" => $newfirstpageid))) { - print_error("Moveit: newlastpageid not found"); - } - if (!$DB->set_field("lesson_pages", "prevpageid", 0, array("id" => $newfirstpageid))) { - print_error("Moveit: unable to update link"); - } - if (!$DB->set_field("lesson_pages", "nextpageid", 0, array("id" => $newlastpageid))) { - print_error("Moveit: unable to update link"); - } - lesson_set_message(get_string('movedpage', 'lesson'), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - diff --git a/mod/lesson/action/updatepage.php b/mod/lesson/action/updatepage.php deleted file mode 100644 index 55780bb0c3..0000000000 --- a/mod/lesson/action/updatepage.php +++ /dev/null @@ -1,169 +0,0 @@ -id = clean_param($form->pageid, PARAM_INT); - - // check to see if the cancel button was pushed - if (optional_param('cancel', '', PARAM_ALPHA)) { - if ($redirect == 'navigation') { - // redirect to viewing the page - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=$page->id"); - } else { - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - } - } - - $page->timemodified = $timenow; - $page->qtype = clean_param($form->qtype, PARAM_INT); - if (isset($form->qoption)) { - $page->qoption = clean_param($form->qoption, PARAM_INT); - } else { - $page->qoption = 0; - } - if (isset($form->layout)) { - $page->layout = clean_param($form->layout, PARAM_INT); - } else { - $page->layout = 0; - } - if (isset($form->display)) { - $page->display = clean_param($form->display, PARAM_INT); - } else { - $page->display = 0; - } - $page->title = clean_param($form->title, PARAM_CLEANHTML); - $page->contents = trim($form->contents); - $page->title = $page->title; - - $DB->update_record("lesson_pages", $page); - if ($page->qtype == LESSON_ENDOFBRANCH || $page->qtype == LESSON_ESSAY || $page->qtype == LESSON_CLUSTER || $page->qtype == LESSON_ENDOFCLUSTER) { - // there's just a single answer with a jump - $oldanswer = new stdClass; - $oldanswer->id = $form->answerid[0]; - $oldanswer->timemodified = $timenow; - $oldanswer->jumpto = clean_param($form->jumpto[0], PARAM_INT); - if (isset($form->score[0])) { - $oldanswer->score = clean_param($form->score[0], PARAM_INT); - } - // delete other answers this if mainly for essay questions. If one switches from using a qtype like Multichoice, - // then switches to essay, the old answers need to be removed because essay is - // supposed to only have one answer record - $params = array ("pageid" => $page->id); - if ($answers = $DB->get_records_select("lesson_answers", "pageid = :pageid", $params)) { - foreach ($answers as $answer) { - if ($answer->id != clean_param($form->answerid[0], PARAM_INT)) { - $DB->delete_records("lesson_answers", array("id" => $answer->id)); - } - } - } - $DB->update_record("lesson_answers", $oldanswer); - } else { - // it's an "ordinary" page - if ($page->qtype == LESSON_MATCHING) { - // need to add two to offset correct response and wrong response - $lesson->maxanswers = $lesson->maxanswers + 2; - } - for ($i = 0; $i < $lesson->maxanswers; $i++) { - // strip tags because the editor gives


... - // also save any answers where the editor is (going to be) used - if ((isset($form->answer[$i]) and (trim(strip_tags($form->answer[$i]))) != '') or isset($form->answereditor[$i]) or isset($form->responseeditor[$i])) { - if ($form->answerid[$i]) { - $oldanswer = new stdClass; - $oldanswer->id = clean_param($form->answerid[$i], PARAM_INT); - if (!isset($form->answereditor[$i])) { - $form->answereditor[$i] = 0; - } - if (!isset($form->responseeditor[$i])) { - $form->responseeditor[$i] = 0; - } - $oldanswer->flags = $form->answereditor[$i] * LESSON_ANSWER_EDITOR + - $form->responseeditor[$i] * LESSON_RESPONSE_EDITOR; - $oldanswer->timemodified = $timenow; - $oldanswer->answer = trim($form->answer[$i]); - if (isset($form->response[$i])) { - $oldanswer->response = trim($form->response[$i]); - } else { - $oldanswer->response = ''; - } - $oldanswer->jumpto = clean_param($form->jumpto[$i], PARAM_INT); - if (isset($form->score[$i])) { - $oldanswer->score = clean_param($form->score[$i], PARAM_INT); - } - $DB->update_record("lesson_answers", $oldanswer); - } else { - // it's a new answer - $newanswer = new stdClass; // need to clear id if more than one new answer is ben added - $newanswer->lessonid = $lesson->id; - $newanswer->pageid = $page->id; - if (!isset($form->answereditor[$i])) { - $form->answereditor[$i] = 0; - } - if (!isset($form->responseeditor[$i])) { - $form->responseeditor[$i] = 0; - } - $newanswer->flags = $form->answereditor[$i] * LESSON_ANSWER_EDITOR + - $form->responseeditor[$i] * LESSON_RESPONSE_EDITOR; - $newanswer->timecreated = $timenow; - $newanswer->answer = trim($form->answer[$i]); - if (isset($form->response[$i])) { - $newanswer->response = trim($form->response[$i]); - } - $newanswer->jumpto = clean_param($form->jumpto[$i], PARAM_INT); - if (isset($form->score[$i])) { - $newanswer->score = clean_param($form->score[$i], PARAM_INT); - } - $newanswerid = $DB->insert_record("lesson_answers", $newanswer); - } - } else { - if ($form->qtype == LESSON_MATCHING) { - if ($i >= 2) { - if ($form->answerid[$i]) { - // need to delete blanked out answer - $DB->delete_records("lesson_answers", array("id" => clean_param($form->answerid[$i], PARAM_INT))); - } - } else { - $oldanswer = new stdClass; - $oldanswer->id = clean_param($form->answerid[$i], PARAM_INT); - if (!isset($form->answereditor[$i])) { - $form->answereditor[$i] = 0; - } - if (!isset($form->responseeditor[$i])) { - $form->responseeditor[$i] = 0; - } - $oldanswer->flags = $form->answereditor[$i] * LESSON_ANSWER_EDITOR + - $form->responseeditor[$i] * LESSON_RESPONSE_EDITOR; - $oldanswer->timemodified = $timenow; - $oldanswer->answer = NULL; - $DB->update_record("lesson_answers", $oldanswer); - } - } elseif (!empty($form->answerid[$i])) { - // need to delete blanked out answer - $DB->delete_records("lesson_answers", array("id" => clean_param($form->answerid[$i], PARAM_INT))); - } - } - } - } - - if ($form->redisplay) { - redirect("$CFG->wwwroot/mod/lesson/lesson.php?id=$cm->id&action=editpage&pageid=$page->id&redirect=$redirect"); - } - - lesson_set_message(get_string('updatedpage', 'lesson').': '.format_string($page->title, true), 'notifysuccess'); - if ($redirect == 'navigation') { - // takes us back to viewing the page - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=$page->id"); - } else { - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); - } - diff --git a/mod/lesson/backuplib.php b/mod/lesson/backuplib.php index de2b0feb1f..b9fc75c365 100644 --- a/mod/lesson/backuplib.php +++ b/mod/lesson/backuplib.php @@ -1,537 +1,503 @@ . + /** * Lesson's backup routine * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - //This is the "graphical" structure of the lesson mod: - // - // lesson_default lesson ----------------------------|--------------------------|--------------------------| - // (UL, pk->id,fk->courseid) (CL,pk->id) | | | - // | | | | - // | lesson_grades lesson_high_scores lesson_timer - // | (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) - // | - // | - // lesson_pages---------------------------| - // (CL,pk->id,fk->lessonid) | - // | | - // | lesson_branch - // | (UL, pk->id,fk->pageid) - // lesson_answers - // (CL,pk->id,fk->pageid) - // | - // | - // | - // lesson_attempts - // (UL,pk->id,fk->answerid) - // - // Meaning: pk->primary key field of the table - // fk->foreign key to link with parent - // nt->nested field (recursive data) - // CL->course level info - // UL->user level info - // files->table may have files) - // - //----------------------------------------------------------- - - //This function executes all the backup procedure about this mod - function lesson_backup_mods($bf, $preferences) { - - global $CFG, $DB; - - $status = true; - - //Iterate over lesson table - $lessons = $DB->get_records("lesson", array ("course" => $preferences->backup_course), "id"); - if ($lessons) { - foreach ($lessons as $lesson) { - if (backup_mod_selected($preferences,'lesson',$lesson->id)) { - $status = lesson_backup_one_mod($bf,$preferences,$lesson); - } + +// This is the "graphical" structure of the lesson mod: +// +// lesson ----------------------------|--------------------------|--------------------------| +// (CL,pk->id) | | | +// | | | | +// | lesson_grades lesson_high_scores lesson_timer +// | (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) +// | +// | +// lesson_pages---------------------------| +// (CL,pk->id,fk->lessonid) | +// | | +// | lesson_branch +// | (UL, pk->id,fk->pageid) +// lesson_answers +// (CL,pk->id,fk->pageid) +// | +// | +// | +// lesson_attempts +// (UL,pk->id,fk->answerid) +// +// Meaning: pk->primary key field of the table +// fk->foreign key to link with parent +// nt->nested field (recursive data) +// CL->course level info +// UL->user level info +// files->table may have files) +// +//----------------------------------------------------------- + +/** + * This function executes all the backup procedure about this mod + */ +function lesson_backup_mods($bf, $preferences) { + + global $CFG, $DB; + + $status = true; + + //Iterate over lesson table + $lessons = $DB->get_records("lesson", array ("course" => $preferences->backup_course), "id"); + if ($lessons) { + foreach ($lessons as $lesson) { + if (backup_mod_selected($preferences,'lesson',$lesson->id)) { + $status = lesson_backup_one_mod($bf,$preferences,$lesson); } } - return $status; } + return $status; +} - function lesson_backup_one_mod($bf,$preferences,$lesson) { +function lesson_backup_one_mod($bf,$preferences,$lesson) { - global $CFG, $DB; + global $CFG, $DB; - if (is_numeric($lesson)) { - $lesson = $DB->get_record('lesson',array ('id' => $lesson)); - } + if (is_numeric($lesson)) { + $lesson = $DB->get_record('lesson',array ('id' => $lesson)); + } - $status = true; - - //Start mod - fwrite ($bf,start_tag("MOD",3,true)); - //Print lesson data - fwrite ($bf,full_tag("ID",4,false,$lesson->id)); - fwrite ($bf,full_tag("MODTYPE",4,false,"lesson")); - fwrite ($bf,full_tag("NAME",4,false,$lesson->name)); - fwrite ($bf,full_tag("PRACTICE",4,false,$lesson->practice)); - fwrite ($bf,full_tag("MODATTEMPTS",4,false,$lesson->modattempts)); - fwrite ($bf,full_tag("USEPASSWORD",4,false,$lesson->usepassword)); - fwrite ($bf,full_tag("PASSWORD",4,false,$lesson->password)); - fwrite ($bf,full_tag("DEPENDENCY",4,false,$lesson->dependency)); - fwrite ($bf,full_tag("CONDITIONS",4,false,$lesson->conditions)); - fwrite ($bf,full_tag("GRADE",4,false,$lesson->grade)); - fwrite ($bf,full_tag("CUSTOM",4,false,$lesson->custom)); - fwrite ($bf,full_tag("ONGOING",4,false,$lesson->ongoing)); - fwrite ($bf,full_tag("USEMAXGRADE",4,false,$lesson->usemaxgrade)); - fwrite ($bf,full_tag("MAXANSWERS",4,false,$lesson->maxanswers)); - fwrite ($bf,full_tag("MAXATTEMPTS",4,false,$lesson->maxattempts)); - fwrite ($bf,full_tag("REVIEW",4,false,$lesson->review)); - fwrite ($bf,full_tag("NEXTPAGEDEFAULT",4,false,$lesson->nextpagedefault)); - fwrite ($bf,full_tag("FEEDBACK",4,false,$lesson->feedback)); - fwrite ($bf,full_tag("MINQUESTIONS",4,false,$lesson->minquestions)); - fwrite ($bf,full_tag("MAXPAGES",4,false,$lesson->maxpages)); - fwrite ($bf,full_tag("TIMED",4,false,$lesson->timed)); - fwrite ($bf,full_tag("MAXTIME",4,false,$lesson->maxtime)); - fwrite ($bf,full_tag("RETAKE",4,false,$lesson->retake)); - fwrite ($bf,full_tag("ACTIVITYLINK",4,false,$lesson->activitylink)); - fwrite ($bf,full_tag("MEDIAFILE",4,false,$lesson->mediafile)); - fwrite ($bf,full_tag("MEDIAHEIGHT",4,false,$lesson->mediaheight)); - fwrite ($bf,full_tag("MEDIAWIDTH",4,false,$lesson->mediawidth)); - fwrite ($bf,full_tag("MEDIACLOSE",4,false,$lesson->mediaclose)); - fwrite ($bf,full_tag("SLIDESHOW",4,false,$lesson->slideshow)); - fwrite ($bf,full_tag("WIDTH",4,false,$lesson->width)); - fwrite ($bf,full_tag("HEIGHT",4,false,$lesson->height)); - fwrite ($bf,full_tag("BGCOLOR",4,false,$lesson->bgcolor)); - fwrite ($bf,full_tag("DISPLAYLEFT",4,false,$lesson->displayleft)); - fwrite ($bf,full_tag("DISPLAYLEFTIF",4,false,$lesson->displayleftif)); - fwrite ($bf,full_tag("PROGRESSBAR",4,false,$lesson->progressbar)); - fwrite ($bf,full_tag("SHOWHIGHSCORES",4,false,$lesson->highscores)); - fwrite ($bf,full_tag("MAXHIGHSCORES",4,false,$lesson->maxhighscores)); - fwrite ($bf,full_tag("AVAILABLE",4,false,$lesson->available)); - fwrite ($bf,full_tag("DEADLINE",4,false,$lesson->deadline)); - fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$lesson->timemodified)); - - //Now we backup lesson pages - $status = backup_lesson_pages($bf,$preferences,$lesson->id); - //if we've selected to backup users info, then backup grades, high scores, and timer info - if ($status) { - if (backup_userdata_selected($preferences,'lesson',$lesson->id)) { - if(!backup_lesson_grades($bf, $preferences, $lesson->id)) { - return false; - } - if (!backup_lesson_high_scores($bf, $preferences, $lesson->id)) { - return false; - } - if (!backup_lesson_timer($bf, $preferences, $lesson->id)) { - return false; - } + $status = true; + + //Start mod + fwrite ($bf,start_tag("MOD",3,true)); + //Print lesson data + fwrite ($bf,full_tag("ID",4,false,$lesson->id)); + fwrite ($bf,full_tag("MODTYPE",4,false,"lesson")); + fwrite ($bf,full_tag("NAME",4,false,$lesson->name)); + fwrite ($bf,full_tag("PRACTICE",4,false,$lesson->practice)); + fwrite ($bf,full_tag("MODATTEMPTS",4,false,$lesson->modattempts)); + fwrite ($bf,full_tag("USEPASSWORD",4,false,$lesson->usepassword)); + fwrite ($bf,full_tag("PASSWORD",4,false,$lesson->password)); + fwrite ($bf,full_tag("DEPENDENCY",4,false,$lesson->dependency)); + fwrite ($bf,full_tag("CONDITIONS",4,false,$lesson->conditions)); + fwrite ($bf,full_tag("GRADE",4,false,$lesson->grade)); + fwrite ($bf,full_tag("CUSTOM",4,false,$lesson->custom)); + fwrite ($bf,full_tag("ONGOING",4,false,$lesson->ongoing)); + fwrite ($bf,full_tag("USEMAXGRADE",4,false,$lesson->usemaxgrade)); + fwrite ($bf,full_tag("MAXANSWERS",4,false,$lesson->maxanswers)); + fwrite ($bf,full_tag("MAXATTEMPTS",4,false,$lesson->maxattempts)); + fwrite ($bf,full_tag("REVIEW",4,false,$lesson->review)); + fwrite ($bf,full_tag("NEXTPAGEDEFAULT",4,false,$lesson->nextpagedefault)); + fwrite ($bf,full_tag("FEEDBACK",4,false,$lesson->feedback)); + fwrite ($bf,full_tag("MINQUESTIONS",4,false,$lesson->minquestions)); + fwrite ($bf,full_tag("MAXPAGES",4,false,$lesson->maxpages)); + fwrite ($bf,full_tag("TIMED",4,false,$lesson->timed)); + fwrite ($bf,full_tag("MAXTIME",4,false,$lesson->maxtime)); + fwrite ($bf,full_tag("RETAKE",4,false,$lesson->retake)); + fwrite ($bf,full_tag("ACTIVITYLINK",4,false,$lesson->activitylink)); + fwrite ($bf,full_tag("MEDIAFILE",4,false,$lesson->mediafile)); + fwrite ($bf,full_tag("MEDIAHEIGHT",4,false,$lesson->mediaheight)); + fwrite ($bf,full_tag("MEDIAWIDTH",4,false,$lesson->mediawidth)); + fwrite ($bf,full_tag("MEDIACLOSE",4,false,$lesson->mediaclose)); + fwrite ($bf,full_tag("SLIDESHOW",4,false,$lesson->slideshow)); + fwrite ($bf,full_tag("WIDTH",4,false,$lesson->width)); + fwrite ($bf,full_tag("HEIGHT",4,false,$lesson->height)); + fwrite ($bf,full_tag("BGCOLOR",4,false,$lesson->bgcolor)); + fwrite ($bf,full_tag("DISPLAYLEFT",4,false,$lesson->displayleft)); + fwrite ($bf,full_tag("DISPLAYLEFTIF",4,false,$lesson->displayleftif)); + fwrite ($bf,full_tag("PROGRESSBAR",4,false,$lesson->progressbar)); + fwrite ($bf,full_tag("SHOWHIGHSCORES",4,false,$lesson->highscores)); + fwrite ($bf,full_tag("MAXHIGHSCORES",4,false,$lesson->maxhighscores)); + fwrite ($bf,full_tag("AVAILABLE",4,false,$lesson->available)); + fwrite ($bf,full_tag("DEADLINE",4,false,$lesson->deadline)); + fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$lesson->timemodified)); + + //Now we backup lesson pages + $status = backup_lesson_pages($bf,$preferences,$lesson->id); + //if we've selected to backup users info, then backup grades, high scores, and timer info + if ($status) { + if (backup_userdata_selected($preferences,'lesson',$lesson->id)) { + if(!backup_lesson_grades($bf, $preferences, $lesson->id)) { + return false; + } + if (!backup_lesson_high_scores($bf, $preferences, $lesson->id)) { + return false; } - // back up the default for the course. There might not be one, but if there - // is, there will only be one. - $status = backup_lesson_default($bf,$preferences); - //End mod - if ($status) { - $status =fwrite ($bf,end_tag("MOD",3,true)); + if (!backup_lesson_timer($bf, $preferences, $lesson->id)) { + return false; } } - - return $status; + //End mod + $status =fwrite ($bf,end_tag("MOD",3,true)); } - //Backup lesson_pages contents (executed from lesson_backup_mods) - function backup_lesson_pages ($bf, $preferences, $lessonid) { - - global $CFG, $DB; - - $status = true; - - // run through the pages in their logical order, get the first page - $params = array ("lessonid" => $lessonid, "prevpageid" => 0); - if ($page = $DB->get_record_select("lesson_pages", "lessonid = :lessonid AND prevpageid = :prevpageid", $params)) { - //Write start tag - $status =fwrite ($bf,start_tag("PAGES",4,true)); - //Iterate over each page - while (true) { - //Start of page - $status =fwrite ($bf,start_tag("PAGE",5,true)); - //Print page contents (prevpageid and nextpageid not needed) - fwrite ($bf,full_tag("PAGEID",6,false,$page->id)); // needed to fix (absolute) jumps - fwrite ($bf,full_tag("QTYPE",6,false,$page->qtype)); - fwrite ($bf,full_tag("QOPTION",6,false,$page->qoption)); - fwrite ($bf,full_tag("LAYOUT",6,false,$page->layout)); - fwrite ($bf,full_tag("DISPLAY",6,false,$page->display)); - fwrite ($bf,full_tag("TIMECREATED",6,false,$page->timecreated)); - fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$page->timemodified)); - fwrite ($bf,full_tag("TITLE",6,false,$page->title)); - fwrite ($bf,full_tag("CONTENTS",6,false,$page->contents)); - //Now we backup lesson answers for this page - $status = backup_lesson_answers($bf, $preferences, $page->id); - // backup branch table info for branch tables. - if ($status && backup_userdata_selected($preferences,'lesson',$lessonid)) { - if (!backup_lesson_branch($bf, $preferences, $page->id)) { - return false; - } + return $status; +} + +//Backup lesson_pages contents (executed from lesson_backup_mods) +function backup_lesson_pages ($bf, $preferences, $lessonid) { + + global $CFG, $DB; + + $status = true; + + // run through the pages in their logical order, get the first page + $params = array ("lessonid" => $lessonid, "prevpageid" => 0); + if ($page = $DB->get_record_select("lesson_pages", "lessonid = :lessonid AND prevpageid = :prevpageid", $params)) { + //Write start tag + $status =fwrite ($bf,start_tag("PAGES",4,true)); + //Iterate over each page + while (true) { + //Start of page + $status =fwrite ($bf,start_tag("PAGE",5,true)); + //Print page contents (prevpageid and nextpageid not needed) + fwrite ($bf,full_tag("PAGEID",6,false,$page->id)); // needed to fix (absolute) jumps + fwrite ($bf,full_tag("QTYPE",6,false,$page->qtype)); + fwrite ($bf,full_tag("QOPTION",6,false,$page->qoption)); + fwrite ($bf,full_tag("LAYOUT",6,false,$page->layout)); + fwrite ($bf,full_tag("DISPLAY",6,false,$page->display)); + fwrite ($bf,full_tag("TIMECREATED",6,false,$page->timecreated)); + fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$page->timemodified)); + fwrite ($bf,full_tag("TITLE",6,false,$page->title)); + fwrite ($bf,full_tag("CONTENTS",6,false,$page->contents)); + //Now we backup lesson answers for this page + $status = backup_lesson_answers($bf, $preferences, $page->id); + // backup branch table info for branch tables. + if ($status && backup_userdata_selected($preferences,'lesson',$lessonid)) { + if (!backup_lesson_branch($bf, $preferences, $page->id)) { + return false; } - //End of page - $status =fwrite ($bf,end_tag("PAGE",5,true)); - // move to the next (logical) page - if ($page->nextpageid) { - if (!$page = $DB->get_record("lesson_pages", array ("id" => $page->nextpageid))) { - print_error('cannotfindnextpage', 'lesson'); - } - } else { - // last page reached - break; + } + //End of page + $status =fwrite ($bf,end_tag("PAGE",5,true)); + // move to the next (logical) page + if ($page->nextpageid) { + if (!$page = $DB->get_record("lesson_pages", array ("id" => $page->nextpageid))) { + print_error('cannotfindnextpage', 'lesson'); } - + } else { + // last page reached + break; } - //Write end tag - $status =fwrite ($bf,end_tag("PAGES",4,true)); + } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("PAGES",4,true)); } - - //Backup lesson_answers contents (executed from backup_lesson_pages) - function backup_lesson_answers($bf,$preferences,$pageno) { - - global $CFG, $DB; - - $status = true; - - // get the answers in a set order, the id order - $lesson_answers = $DB->get_records("lesson_answers", array("pageid" => $pageno), "id"); - - //If there is lesson_answers - if ($lesson_answers) { - //Write start tag - $status =fwrite ($bf,start_tag("ANSWERS",6,true)); - //Iterate over each element - foreach ($lesson_answers as $answer) { - //Start answer - $status =fwrite ($bf,start_tag("ANSWER",7,true)); - //Print answer contents - fwrite ($bf,full_tag("ID",8,false,$answer->id)); - fwrite ($bf,full_tag("JUMPTO",8,false,$answer->jumpto)); - fwrite ($bf,full_tag("GRADE",8,false,$answer->grade)); - fwrite ($bf,full_tag("SCORE",8,false,$answer->score)); - fwrite ($bf,full_tag("FLAGS",8,false,$answer->flags)); - fwrite ($bf,full_tag("TIMECREATED",8,false,$answer->timecreated)); - fwrite ($bf,full_tag("TIMEMODIFIED",8,false,$answer->timemodified)); - fwrite ($bf,full_tag("ANSWERTEXT",8,false,$answer->answer)); - fwrite ($bf,full_tag("RESPONSE",8,false,$answer->response)); - //Now we backup any lesson attempts (if student data required) - if (backup_userdata_selected($preferences,'lesson',$answer->lessonid)) { - $status = backup_lesson_attempts($bf,$preferences,$answer->id); - } - //End rubric - $status =fwrite ($bf,end_tag("ANSWER",7,true)); + return $status; +} + +//Backup lesson_answers contents (executed from backup_lesson_pages) +function backup_lesson_answers($bf,$preferences,$pageno) { + + global $CFG, $DB; + + $status = true; + + // get the answers in a set order, the id order + $lesson_answers = $DB->get_records("lesson_answers", array("pageid" => $pageno), "id"); + + //If there is lesson_answers + if ($lesson_answers) { + //Write start tag + $status =fwrite ($bf,start_tag("ANSWERS",6,true)); + //Iterate over each element + foreach ($lesson_answers as $answer) { + //Start answer + $status =fwrite ($bf,start_tag("ANSWER",7,true)); + //Print answer contents + fwrite ($bf,full_tag("ID",8,false,$answer->id)); + fwrite ($bf,full_tag("JUMPTO",8,false,$answer->jumpto)); + fwrite ($bf,full_tag("GRADE",8,false,$answer->grade)); + fwrite ($bf,full_tag("SCORE",8,false,$answer->score)); + fwrite ($bf,full_tag("FLAGS",8,false,$answer->flags)); + fwrite ($bf,full_tag("TIMECREATED",8,false,$answer->timecreated)); + fwrite ($bf,full_tag("TIMEMODIFIED",8,false,$answer->timemodified)); + fwrite ($bf,full_tag("ANSWERTEXT",8,false,$answer->answer)); + fwrite ($bf,full_tag("RESPONSE",8,false,$answer->response)); + //Now we backup any lesson attempts (if student data required) + if (backup_userdata_selected($preferences,'lesson',$answer->lessonid)) { + $status = backup_lesson_attempts($bf,$preferences,$answer->id); } - //Write end tag - $status =fwrite ($bf,end_tag("ANSWERS",6,true)); + //End rubric + $status =fwrite ($bf,end_tag("ANSWER",7,true)); } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("ANSWERS",6,true)); } - - //Backup lesson_attempts contents (executed from lesson_backup_answers) - function backup_lesson_attempts ($bf,$preferences,$answerid) { - - global $CFG, $DB; - - $status = true; - - $lesson_attempts = $DB->get_records("lesson_attempts", array("answerid" => $answerid)); - //If there are attempts - if ($lesson_attempts) { - //Write start tag - $status =fwrite ($bf,start_tag("ATTEMPTS",8,true)); - //Iterate over each attempt - foreach ($lesson_attempts as $attempt) { - //Start Attempt - $status =fwrite ($bf,start_tag("ATTEMPT",9,true)); - //Print attempt contents - fwrite ($bf,full_tag("USERID",10,false,$attempt->userid)); - fwrite ($bf,full_tag("RETRY",10,false,$attempt->retry)); - fwrite ($bf,full_tag("CORRECT",10,false,$attempt->correct)); - fwrite ($bf,full_tag("USERANSWER",10,false,$attempt->useranswer)); - fwrite ($bf,full_tag("TIMESEEN",10,false,$attempt->timeseen)); - //End attempt - $status =fwrite ($bf,end_tag("ATTEMPT",9,true)); - } - //Write end tag - $status =fwrite ($bf,end_tag("ATTEMPTS",8,true)); + return $status; +} + +//Backup lesson_attempts contents (executed from lesson_backup_answers) +function backup_lesson_attempts ($bf,$preferences,$answerid) { + + global $CFG, $DB; + + $status = true; + + $lesson_attempts = $DB->get_records("lesson_attempts", array("answerid" => $answerid)); + //If there are attempts + if ($lesson_attempts) { + //Write start tag + $status =fwrite ($bf,start_tag("ATTEMPTS",8,true)); + //Iterate over each attempt + foreach ($lesson_attempts as $attempt) { + //Start Attempt + $status =fwrite ($bf,start_tag("ATTEMPT",9,true)); + //Print attempt contents + fwrite ($bf,full_tag("USERID",10,false,$attempt->userid)); + fwrite ($bf,full_tag("RETRY",10,false,$attempt->retry)); + fwrite ($bf,full_tag("CORRECT",10,false,$attempt->correct)); + fwrite ($bf,full_tag("USERANSWER",10,false,$attempt->useranswer)); + fwrite ($bf,full_tag("TIMESEEN",10,false,$attempt->timeseen)); + //End attempt + $status =fwrite ($bf,end_tag("ATTEMPT",9,true)); } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("ATTEMPTS",8,true)); } - - - //Backup lesson_grades contents (executed from backup_lesson_mods) - function backup_lesson_grades ($bf,$preferences,$lessonid) { - - global $CFG, $DB; - - $status = true; - - $grades = $DB->get_records("lesson_grades", array("lessonid" => $lessonid)); - - //If there is grades - if ($grades) { - //Write start tag - $status =fwrite ($bf,start_tag("GRADES",4,true)); - //Iterate over each grade - foreach ($grades as $grade) { - //Start grade - $status =fwrite ($bf,start_tag("GRADE",5,true)); - //Print grade contents - fwrite ($bf,full_tag("USERID",6,false,$grade->userid)); - fwrite ($bf,full_tag("GRADE_VALUE",6,false,$grade->grade)); - fwrite ($bf,full_tag("LATE",6,false,$grade->late)); - fwrite ($bf,full_tag("COMPLETED",6,false,$grade->completed)); - //End grade - $status =fwrite ($bf,end_tag("GRADE",5,true)); - } - //Write end tag - $status =fwrite ($bf,end_tag("GRADES",4,true)); + return $status; +} + + +//Backup lesson_grades contents (executed from backup_lesson_mods) +function backup_lesson_grades ($bf,$preferences,$lessonid) { + + global $CFG, $DB; + + $status = true; + + $grades = $DB->get_records("lesson_grades", array("lessonid" => $lessonid)); + + //If there is grades + if ($grades) { + //Write start tag + $status =fwrite ($bf,start_tag("GRADES",4,true)); + //Iterate over each grade + foreach ($grades as $grade) { + //Start grade + $status =fwrite ($bf,start_tag("GRADE",5,true)); + //Print grade contents + fwrite ($bf,full_tag("USERID",6,false,$grade->userid)); + fwrite ($bf,full_tag("GRADE_VALUE",6,false,$grade->grade)); + fwrite ($bf,full_tag("LATE",6,false,$grade->late)); + fwrite ($bf,full_tag("COMPLETED",6,false,$grade->completed)); + //End grade + $status =fwrite ($bf,end_tag("GRADE",5,true)); } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("GRADES",4,true)); } - - //Backup lesson_branch contents (executed from backup_lesson_pages) - function backup_lesson_branch($bf,$preferences,$pageno) { - - global $CFG, $DB; - - $status = true; - - // get the branches in a set order, the id order - $lesson_branch = $DB->get_records("lesson_branch", array("pageid" => $pageno), "id"); - - //If there is lesson_branch - if ($lesson_branch) { - //Write start tag - $status =fwrite ($bf,start_tag("BRANCHES",6,true)); - //Iterate over each element - foreach ($lesson_branch as $branch) { - //Start branch - $status =fwrite ($bf,start_tag("BRANCH",7,true)); - //Print branch contents - fwrite ($bf,full_tag("USERID",8,false,$branch->userid)); - fwrite ($bf,full_tag("RETRY",8,false,$branch->retry)); - fwrite ($bf,full_tag("FLAG",8,false,$branch->flag)); - fwrite ($bf,full_tag("TIMESEEN",8,false,$branch->timeseen)); - // END BRANCH - $status =fwrite ($bf,end_tag("BRANCH",7,true)); - } - //Write end tag - $status =fwrite ($bf,end_tag("BRANCHES",6,true)); + return $status; +} + +//Backup lesson_branch contents (executed from backup_lesson_pages) +function backup_lesson_branch($bf,$preferences,$pageno) { + + global $CFG, $DB; + + $status = true; + + // get the branches in a set order, the id order + $lesson_branch = $DB->get_records("lesson_branch", array("pageid" => $pageno), "id"); + + //If there is lesson_branch + if ($lesson_branch) { + //Write start tag + $status =fwrite ($bf,start_tag("BRANCHES",6,true)); + //Iterate over each element + foreach ($lesson_branch as $branch) { + //Start branch + $status =fwrite ($bf,start_tag("BRANCH",7,true)); + //Print branch contents + fwrite ($bf,full_tag("USERID",8,false,$branch->userid)); + fwrite ($bf,full_tag("RETRY",8,false,$branch->retry)); + fwrite ($bf,full_tag("FLAG",8,false,$branch->flag)); + fwrite ($bf,full_tag("TIMESEEN",8,false,$branch->timeseen)); + // END BRANCH + $status =fwrite ($bf,end_tag("BRANCH",7,true)); } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("BRANCHES",6,true)); } - - //Backup lesson_timer contents (executed from backup_lesson_mods) - function backup_lesson_timer ($bf,$preferences,$lessonid) { - - global $CFG, $DB; - - $status = true; - - $times = $DB->get_records("lesson_timer", array("lessonid" => $lessonid)); - - //If there is times - if ($times) { - //Write start tag - $status =fwrite ($bf,start_tag("TIMES",4,true)); - //Iterate over each time - foreach ($times as $time) { - //Start time - $status =fwrite ($bf,start_tag("TIME",5,true)); - //Print time contents - fwrite ($bf,full_tag("USERID",6,false,$time->userid)); - fwrite ($bf,full_tag("STARTTIME",6,false,$time->starttime)); - fwrite ($bf,full_tag("LESSONTIME",6,false,$time->lessontime)); - //End time - $status =fwrite ($bf,end_tag("TIME",5,true)); - } - //Write end tag - $status =fwrite ($bf,end_tag("TIMES",4,true)); + return $status; +} + +//Backup lesson_timer contents (executed from backup_lesson_mods) +function backup_lesson_timer ($bf,$preferences,$lessonid) { + + global $CFG, $DB; + + $status = true; + + $times = $DB->get_records("lesson_timer", array("lessonid" => $lessonid)); + + //If there is times + if ($times) { + //Write start tag + $status =fwrite ($bf,start_tag("TIMES",4,true)); + //Iterate over each time + foreach ($times as $time) { + //Start time + $status =fwrite ($bf,start_tag("TIME",5,true)); + //Print time contents + fwrite ($bf,full_tag("USERID",6,false,$time->userid)); + fwrite ($bf,full_tag("STARTTIME",6,false,$time->starttime)); + fwrite ($bf,full_tag("LESSONTIME",6,false,$time->lessontime)); + //End time + $status =fwrite ($bf,end_tag("TIME",5,true)); } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("TIMES",4,true)); } - - // backup lesson_high_score contents (executed from backup_lesson_mods) - function backup_lesson_high_scores($bf, $preferences, $lessonid) { - global $CFG, $DB; - - $status = true; - - $highscores = $DB->get_records("lesson_high_scores", array("lessonid" => $lessonid)); - - //If there is highscores - if ($highscores) { - //Write start tag - $status =fwrite ($bf,start_tag("HIGHSCORES",4,true)); - //Iterate over each highscore - foreach ($highscores as $highscore) { - //Start highscore - $status =fwrite ($bf,start_tag("HIGHSCORE",5,true)); - //Print highscore contents - fwrite ($bf,full_tag("USERID",6,false,$highscore->userid)); - fwrite ($bf,full_tag("GRADEID",6,false,$highscore->gradeid)); - fwrite ($bf,full_tag("NICKNAME",6,false,$highscore->nickname)); - //End highscore - $status =fwrite ($bf,end_tag("HIGHSCORE",5,true)); - } - //Write end tag - $status =fwrite ($bf,end_tag("HIGHSCORES",4,true)); + return $status; +} + +// backup lesson_high_score contents (executed from backup_lesson_mods) +function backup_lesson_high_scores($bf, $preferences, $lessonid) { + global $CFG, $DB; + + $status = true; + + $highscores = $DB->get_records("lesson_high_scores", array("lessonid" => $lessonid)); + + //If there is highscores + if ($highscores) { + //Write start tag + $status =fwrite ($bf,start_tag("HIGHSCORES",4,true)); + //Iterate over each highscore + foreach ($highscores as $highscore) { + //Start highscore + $status =fwrite ($bf,start_tag("HIGHSCORE",5,true)); + //Print highscore contents + fwrite ($bf,full_tag("USERID",6,false,$highscore->userid)); + fwrite ($bf,full_tag("GRADEID",6,false,$highscore->gradeid)); + fwrite ($bf,full_tag("NICKNAME",6,false,$highscore->nickname)); + //End highscore + $status =fwrite ($bf,end_tag("HIGHSCORE",5,true)); } - return $status; + //Write end tag + $status =fwrite ($bf,end_tag("HIGHSCORES",4,true)); } - - // backup lesson_default contents (executed from backup_lesson_mods) - function backup_lesson_default ($bf,$preferences) { - global $CFG, $DB; - - $status = true; - - //only one default record per course - $default = $DB->get_record("lesson_default", array("course" => $preferences->backup_course)); - if ($default) { - //Start mod - $status =fwrite ($bf,start_tag("DEFAULTS",4,true)); - //Print default data - fwrite ($bf,full_tag("PRACTICE",5,false,$default->practice)); - fwrite ($bf,full_tag("MODATTEMPTS",5,false,$default->modattempts)); - fwrite ($bf,full_tag("USEPASSWORD",5,false,$default->usepassword)); - fwrite ($bf,full_tag("PASSWORD",5,false,$default->password)); - fwrite ($bf,full_tag("CONDITIONS",5,false,$default->conditions)); - fwrite ($bf,full_tag("GRADE",5,false,$default->grade)); - fwrite ($bf,full_tag("CUSTOM",5,false,$default->custom)); - fwrite ($bf,full_tag("ONGOING",5,false,$default->ongoing)); - fwrite ($bf,full_tag("USEMAXGRADE",5,false,$default->usemaxgrade)); - fwrite ($bf,full_tag("MAXANSWERS",5,false,$default->maxanswers)); - fwrite ($bf,full_tag("MAXATTEMPTS",5,false,$default->maxattempts)); - fwrite ($bf,full_tag("REVIEW",5,false,$default->review)); - fwrite ($bf,full_tag("NEXTPAGEDEFAULT",5,false,$default->nextpagedefault)); - fwrite ($bf,full_tag("FEEDBACK",5,false,$default->feedback)); - fwrite ($bf,full_tag("MINQUESTIONS",5,false,$default->minquestions)); - fwrite ($bf,full_tag("MAXPAGES",5,false,$default->maxpages)); - fwrite ($bf,full_tag("TIMED",5,false,$default->timed)); - fwrite ($bf,full_tag("MAXTIME",5,false,$default->maxtime)); - fwrite ($bf,full_tag("RETAKE",5,false,$default->retake)); - fwrite ($bf,full_tag("MEDIAHEIGHT",5,false,$default->mediaheight)); - fwrite ($bf,full_tag("MEDIAWIDTH",5,false,$default->mediawidth)); - fwrite ($bf,full_tag("MEDIACLOSE",5,false,$default->mediaclose)); - fwrite ($bf,full_tag("SLIDESHOW",5,false,$default->slideshow)); - fwrite ($bf,full_tag("WIDTH",5,false,$default->width)); - fwrite ($bf,full_tag("HEIGHT",5,false,$default->height)); - fwrite ($bf,full_tag("BGCOLOR",5,false,$default->bgcolor)); - fwrite ($bf,full_tag("DISPLAYLEFT",5,false,$default->displayleft)); - fwrite ($bf,full_tag("DISPLAYLEFTIF",5,false,$default->displayleftif)); - fwrite ($bf,full_tag("PROGRESSBAR",5,false,$default->progressbar)); - fwrite ($bf,full_tag("HIGHSCORES",5,false,$default->highscores)); - fwrite ($bf,full_tag("MAXHIGHSCORES",5,false,$default->maxhighscores)); - $status =fwrite ($bf,end_tag("DEFAULTS",4,true)); + return $status; +} + +//Return an array of info (name,value) +function lesson_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) { + if (!empty($instances) && is_array($instances) && count($instances)) { + $info = array(); + foreach ($instances as $id => $instance) { + $info += lesson_check_backup_mods_instances($instance,$backup_unique_code); } - return $status; + return $info; + } + //First the course data + $info[0][0] = get_string("modulenameplural","lesson"); + if ($ids = lesson_ids($course)) { + $info[0][1] = count($ids); + } else { + $info[0][1] = 0; } - //Return an array of info (name,value) - function lesson_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) { - if (!empty($instances) && is_array($instances) && count($instances)) { - $info = array(); - foreach ($instances as $id => $instance) { - $info += lesson_check_backup_mods_instances($instance,$backup_unique_code); - } - return $info; - } - //First the course data - $info[0][0] = get_string("modulenameplural","lesson"); - if ($ids = lesson_ids($course)) { - $info[0][1] = count($ids); + //Now, if requested, the user_data + if ($user_data) { + $info[1][0] = get_string("attempts","lesson"); + if ($ids = lesson_attempts_ids_by_course ($course)) { + $info[1][1] = count($ids); } else { - $info[0][1] = 0; + $info[1][1] = 0; } - - //Now, if requested, the user_data - if ($user_data) { - $info[1][0] = get_string("attempts","lesson"); - if ($ids = lesson_attempts_ids_by_course ($course)) { - $info[1][1] = count($ids); - } else { - $info[1][1] = 0; - } - } - return $info; } - - //Return an array of info (name,value) - function lesson_check_backup_mods_instances($instance,$backup_unique_code) { - //First the course data - $info[$instance->id.'0'][0] = ''.$instance->name.''; - $info[$instance->id.'0'][1] = ''; - - //Now, if requested, the user_data - if (!empty($instance->userdata)) { - $info[$instance->id.'1'][0] = get_string("attempts","lesson"); - if ($ids = lesson_attempts_ids_by_instance ($instance->id)) { - $info[$instance->id.'1'][1] = count($ids); - } else { - $info[$instance->id.'1'][1] = 0; - } + return $info; +} + +//Return an array of info (name,value) +function lesson_check_backup_mods_instances($instance,$backup_unique_code) { + //First the course data + $info[$instance->id.'0'][0] = ''.$instance->name.''; + $info[$instance->id.'0'][1] = ''; + + //Now, if requested, the user_data + if (!empty($instance->userdata)) { + $info[$instance->id.'1'][0] = get_string("attempts","lesson"); + if ($ids = lesson_attempts_ids_by_instance ($instance->id)) { + $info[$instance->id.'1'][1] = count($ids); + } else { + $info[$instance->id.'1'][1] = 0; } - return $info; } + return $info; +} - //Return a content encoded to support interactivities linking. Every module - //should have its own. They are called automatically from the backup procedure. - function lesson_encode_content_links ($content,$preferences) { +//Return a content encoded to support interactivities linking. Every module +//should have its own. They are called automatically from the backup procedure. +function lesson_encode_content_links ($content,$preferences) { - global $CFG; + global $CFG; - $base = preg_quote($CFG->wwwroot,"/"); + $base = preg_quote($CFG->wwwroot,"/"); - //Link to the list of lessons - $buscar="/(".$base."\/mod\/lesson\/index.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar,'$@LESSONINDEX*$2@$',$content); + //Link to the list of lessons + $buscar="/(".$base."\/mod\/lesson\/index.php\?id\=)([0-9]+)/"; + $result= preg_replace($buscar,'$@LESSONINDEX*$2@$',$content); - //Link to lesson view by moduleid - $buscar="/(".$base."\/mod\/lesson\/view.php\?id\=)([0-9]+)/"; - $result= preg_replace($buscar,'$@LESSONVIEWBYID*$2@$',$result); + //Link to lesson view by moduleid + $buscar="/(".$base."\/mod\/lesson\/view.php\?id\=)([0-9]+)/"; + $result= preg_replace($buscar,'$@LESSONVIEWBYID*$2@$',$result); - return $result; - } + return $result; +} - // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE +// INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE - //Returns an array of lesson id - function lesson_ids ($course) { +//Returns an array of lesson id +function lesson_ids ($course) { - global $CFG, $DB; + global $CFG, $DB; - $params = array ("course" => $course); - return $DB->get_records_sql ("SELECT l.id, l.course - FROM {lesson} l - WHERE l.course = :course", $params); - } + $params = array ("course" => $course); + return $DB->get_records_sql ("SELECT l.id, l.course + FROM {lesson} l + WHERE l.course = :course", $params); +} - //Returns an array of lesson_submissions id - function lesson_attempts_ids_by_course ($course) { +//Returns an array of lesson_submissions id +function lesson_attempts_ids_by_course ($course) { - global $CFG, $DB; + global $CFG, $DB; - $params = array ("course" => $course); - return $DB->get_records_sql ("SELECT a.id , a.lessonid - FROM {lesson_attempts} a, - {lesson} l - WHERE l.course = :course AND - a.lessonid = l.id", $params); - } - - //Returns an array of lesson_submissions id - function lesson_attempts_ids_by_instance ($instanceid) { + $params = array ("course" => $course); + return $DB->get_records_sql ("SELECT a.id , a.lessonid + FROM {lesson_attempts} a, + {lesson} l + WHERE l.course = :course AND + a.lessonid = l.id", $params); +} - global $CFG, $DB; +//Returns an array of lesson_submissions id +function lesson_attempts_ids_by_instance ($instanceid) { - $params = array ("lessonid" => $instanceid); - return $DB->get_records_sql ("SELECT a.id , a.lessonid - FROM {lesson_attempts} a - WHERE a.lessonid = :lessonid", $params); - } + global $CFG, $DB; + $params = array ("lessonid" => $instanceid); + return $DB->get_records_sql ("SELECT a.id , a.lessonid + FROM {lesson_attempts} a + WHERE a.lessonid = :lessonid", $params); +} \ No newline at end of file diff --git a/mod/lesson/continue.php b/mod/lesson/continue.php new file mode 100644 index 0000000000..a943f0d247 --- /dev/null +++ b/mod/lesson/continue.php @@ -0,0 +1,199 @@ +. + +/** + * Action for processing page answers by users + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** Require the specific libraries */ +require_once("../../config.php"); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); + +try { + $cm = get_coursemodule_from_id('lesson', required_param('id', PARAM_INT), 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} + +require_login($course, false, $cm); +require_sesskey(); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +$canmanage = has_capability('mod/lesson:manage', $context); +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); + +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/continue.php', array('id'=>$cm->id)); +$PAGE->set_url($url); +$PAGE->navbar->add(get_string('continue', 'lesson')); + +// This is the code updates the lesson time for a timed test +// get time information for this user +if (!$canmanage) { + $lesson->displayleft = lesson_displayleftif($lesson); + $timer = $lesson->update_timer(); + if ($lesson->timed) { + $timeleft = ($timer->starttime + $lesson->maxtime * 60) - time(); + if ($timeleft <= 0) { + // Out of time + $lesson->add_message(get_string('eolstudentoutoftime', 'lesson')); + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$cm->id,'pageid'=>LESSON_EOL, 'outoftime'=>'normal'))); + } else if ($timeleft < 60) { + // One minute warning + $lesson->add_message(get_string("studentoneminwarning", "lesson")); + } + } +} else { + $timer = new stdClass; +} + +// record answer (if necessary) and show response (if none say if answer is correct or not) +$page = $lesson->load_page(required_param('pageid', PARAM_INT)); +$result = $page->record_attempt($context); + +if (isset($USER->modattempts[$lesson->id])) { + // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time + if ($USER->modattempts[$lesson->id] == $page->id) { // remember, this session variable holds the pageid of the last page that the user saw + $result->newpageid = LESSON_EOL; + } else { + $nretakes--; // make sure we are looking at the right try. + $attempts = $DB->get_records("lesson_attempts", array("lessonid"=>$lesson->id, "userid"=>$USER->id, "retry"=>$nretakes), "timeseen", "id, pageid"); + $found = false; + $temppageid = 0; + foreach($attempts as $attempt) { + if ($found && $temppageid != $attempt->pageid) { // now try to find the next page, make sure next few attempts do no belong to current page + $result->newpageid = $attempt->pageid; + break; + } + if ($attempt->pageid == $page->id) { + $found = true; // if found current page + $temppageid = $attempt->pageid; + } + } + } +} elseif ($result->newpageid != LESSON_CLUSTERJUMP && $page->id != 0 && $result->newpageid > 0) { + // going to check to see if the page that the user is going to view next, is a cluster page. + // If so, dont display, go into the cluster. The $result->newpageid > 0 is used to filter out all of the negative code jumps. + $newpage = $lesson->load_page($result->newpageid); + if ($newpageid = $newpage->override_next_page($result->newpageid)) { + $result->newpageid = $newpageid; + } +} elseif ($result->newpageid == LESSON_UNSEENBRANCHPAGE) { + if ($canmanage) { + if ($page->nextpageid == 0) { + $result->newpageid = LESSON_EOL; + } else { + $result->newpageid = $page->nextpageid; + } + } else { + $result->newpageid = lesson_unseen_question_jump($lesson, $USER->id, $page->id); + } +} elseif ($result->newpageid == LESSON_PREVIOUSPAGE) { + $result->newpageid = $page->prevpageid; +} elseif ($result->newpageid == LESSON_RANDOMPAGE) { + $result->newpageid = lesson_random_question_jump($lesson, $page->id); +} elseif ($result->newpageid == LESSON_CLUSTERJUMP) { + if ($canmanage) { + if ($page->nextpageid == 0) { // if teacher, go to next page + $result->newpageid = LESSON_EOL; + } else { + $result->newpageid = $page->nextpageid; + } + } else { + $result->newpageid = $lesson->cluster_jump($page->id); + } +} + +if ($result->nodefaultresponse) { + // Don't display feedback + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$cm->id,'pageid'=>$result->newpageid))); +} + +/// Set Messages + +if ($canmanage) { + // This is the warning msg for teachers to inform them that cluster and unseen does not work while logged in as a teacher + if(lesson_display_teacher_warning($lesson)) { + $warningvars->cluster = get_string("clusterjump", "lesson"); + $warningvars->unseen = get_string("unseenpageinbranch", "lesson"); + $lesson->add_message(get_string("teacherjumpwarning", "lesson", $warningvars)); + } + // Inform teacher that s/he will not see the timer + if ($lesson->timed) { + $lesson->add_message(get_string("teachertimerwarning", "lesson")); + } +} +// Report attempts remaining +if ($result->attemptsremaining != 0) { + $lesson->add_message(get_string('attemptsremaining', 'lesson', $result->attemptsremaining)); +} +// Report if max attempts reached +if ($result->maxattemptsreached != 0) { + $lesson->add_message('('.get_string("maximumnumberofattemptsreached", "lesson").')'); +} + +$PAGE->set_url('mod/lesson/view.php', array('id' => $cm->id, 'pageid' => $page->id)); +$PAGE->set_subpage($page->id); + +/// Print the header, heading and tabs +lesson_add_pretend_blocks($PAGE, $cm, $lesson, $timer); +echo $lessonoutput->header($lesson, 'view', true, $page->id); + +if ($lesson->displayleft) { + echo ''; +} +// This calculates and prints the ongoing score message +if ($lesson->ongoing) { + echo $lessonoutput->ongoing_score($lesson); +} +echo $result->feedback; + +// User is modifying attempts - save button and some instructions +if (isset($USER->modattempts[$lesson->id])) { + $url = $CFG->wwwroot.'/mod/lesson/view.php'; + $options = array('id'=>$cm->id, 'pageid'=>LESSON_EOL); + $form = html_form::make($url, $options, get_string('savechanges', 'lesson')); + $content = $OUTPUT->box(get_string("savechangesandeol", "lesson"), 'center'); + $content .= $OUTPUT->box(get_string("or", "lesson"), 'center'); + $content .= $OUTPUT->box(get_string("continuetoanswer", "lesson"), 'center'); + echo $OUTPUT->form($form, $content); +} + +// Review button back +if ($lesson->review && !$result->correctanswer && !$result->noanswer && !$result->isessayquestion) { + $url = $CFG->wwwroot.'/mod/lesson/view.php'; + $options = array('id'=>$cm->id, 'pageid'=>$page->id); + $form = html_form::make($url, $options, get_string('reviewquestionback', 'lesson')); + echo $OUTPUT->form($form); +} + +$url = $CFG->wwwroot.'/mod/lesson/view.php'; +$options = array('id'=>$cm->id, 'pageid'=>$result->newpageid); +if ($lesson->review && !$result->correctanswer && !$result->noanswer && !$result->isessayquestion) { + // Review button continue + $form = html_form::make_button($url, $options, get_string('reviewquestioncontinue', 'lesson')); +} else { + // Normal continue button + $form = html_form::make_button($url, $options, get_string('continue', 'lesson')); +} +echo $OUTPUT->button($form); +echo $lessonoutput->footer(); \ No newline at end of file diff --git a/mod/lesson/db/access.php b/mod/lesson/db/access.php index 60adf6ae3b..96707c07a8 100644 --- a/mod/lesson/db/access.php +++ b/mod/lesson/db/access.php @@ -1,9 +1,30 @@ . + /** * Capability definitions for the lesson module. * * For naming conventions, see lib/db/access.php. + * + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late */ + $capabilities = array( 'mod/lesson:edit' => array( diff --git a/mod/lesson/db/install.php b/mod/lesson/db/install.php index 37ae270d34..5501b7650c 100644 --- a/mod/lesson/db/install.php +++ b/mod/lesson/db/install.php @@ -1,9 +1,30 @@ . + +/** + * This file replaces: + * * STATEMENTS section in db/install.xml + * * lib.php/modulename_install() post installation hook + * * partially defaults.php + * + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 o + */ function xmldb_lesson_install() { global $DB; diff --git a/mod/lesson/db/install.xml b/mod/lesson/db/install.xml index 4b18fc038c..e8fe598380 100644 --- a/mod/lesson/db/install.xml +++ b/mod/lesson/db/install.xml @@ -1,5 +1,5 @@ - @@ -48,7 +48,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -116,7 +116,7 @@ - +
@@ -133,47 +133,7 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- +
@@ -225,4 +185,4 @@
-
+ \ No newline at end of file diff --git a/mod/lesson/db/upgrade.php b/mod/lesson/db/upgrade.php index 30941931f8..6649022d99 100644 --- a/mod/lesson/db/upgrade.php +++ b/mod/lesson/db/upgrade.php @@ -1,24 +1,45 @@ . + +/** + * This file keeps track of upgrades to + * the lesson module + * + * Sometimes, changes between versions involve + * alterations to database structures and other + * major things that may break installations. + * + * The upgrade function in this file will attempt + * to perform all the necessary actions to upgrade + * your older installtion to the current version. + * + * If there's something it cannot do itself, it + * will tell you what you need to do. + * + * The commands in here will all be database-neutral, + * using the methods of database_manager class + * + * Please do not forget to use upgrade_set_timeout() + * before any action that may take longer time to finish. + * + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 o + */ function xmldb_lesson_upgrade($oldversion) { global $CFG, $DB; @@ -53,6 +74,89 @@ function xmldb_lesson_upgrade($oldversion) { upgrade_mod_savepoint($result, 2008112601, 'lesson'); } + if ($result && $oldversion < 2009111600) { + /** + * Change the grade field within lesson_answers to an unsigned int and increment + * the length by one to ensure that no values are changed (reduced) + */ + $table = new xmldb_table('lesson_answers'); + $field = new xmldb_field('grade'); + $field->set_attributes(XMLDB_TYPE_INTEGER, '4', false, XMLDB_NOTNULL, null, '0', 'jumpto'); + $dbman->change_field_type($table, $field); + upgrade_mod_savepoint($result, 2009111600, 'lesson'); + } + + if ($result && $oldversion < 2009120400) { + + /** + * Move any media files associated with the lesson to use the new file + * API methods and structures. + */ + $lessons = $DB->get_records_select('lesson', 'mediafile != \'\''); + + $empty = $DB->sql_empty(); // silly oracle empty string handling workaround + $sqlfrom = "FROM {lesson} l + JOIN {modules} m ON m.name = 'lesson' + JOIN {course_modules} cm ON (cm.module = m.id AND cm.instance = l.id) + WHERE l.mediafile <> '$empty'"; + + $count = $DB->count_records_sql("SELECT COUNT('x') $sqlfrom"); + + if ($count > 0 && $rs = $DB->get_recordset_sql("SELECT l.id, l.mediafile, l.course, cm.id AS cmid $sqlfrom ORDER BY l.course, l.id")) { + + $pbar = new progress_bar('migratelessonfiles', 500, true); + $fs = get_file_storage(); + + $i = 0; + foreach ($rs as $lesson) { + $i++; + upgrade_set_timeout(60); // set up timeout, may also abort execution + $pbar->update($i, $count, "Migrating lesson mediafiles - $i/$count."); + + $filepath = $CFG->dataroot.'/'.$lesson->course.'/'.$CFG->moddata.'/lesson/'.$lesson->mediafile; + if (!is_readable($filepath)) { + //file missing?? + echo $OUTPUT->notification("File not readable, skipping: ".$filepath); + $DB->set_field('lesson', 'mediafile', '', array('id'=>$lesson->id)); + continue; + } + + $filearea = 'lesson_media_file'; + $filename = clean_param($lesson->mediafile, PARAM_FILE); + if ($filename === '') { + echo $OUTPUT->notification("Unsupported lesson filename, skipping: ".$filepath); + $DB->set_field('lesson', 'mediafile', '', array('id'=>$lesson->id)); + continue; + } + + $context = get_context_instance(CONTEXT_MODULE, $lesson->cmid); + if (!$fs->file_exists($context->id, $filearea, $lesson->id, '/', $filename)) { + $file_record = array('contextid'=>$context->id, 'filearea'=>$filearea, 'itemid'=>$lesson->id, 'filepath'=>'/', 'filename'=>$filename); + if ($fs->create_file_from_pathname($file_record, $filepath)) { + if ($DB->set_field('lesson', 'mediafile', $filename, array('id'=>$lesson->id))) { + unlink($filepath); + } + } + } + + // remove dir if empty + @rmdir("$CFG->dataroot/$post->course/$CFG->moddata/lesson"); + } + } + + upgrade_mod_savepoint($result, 2009120400, 'lesson'); + } + + if ($result && $oldversion < 2009120800) { + /** + * Drop the lesson_default table, as of Moodle 2.0 it is no longer used + * the module now has a settings.php instead + */ + $table = new xmldb_table('lesson_default'); + $dbman->drop_table($table); + upgrade_mod_savepoint($result, 2009120800, 'lesson'); + } + return $result; } diff --git a/mod/lesson/edit.php b/mod/lesson/edit.php index 83843aa41e..25de1d3ac4 100644 --- a/mod/lesson/edit.php +++ b/mod/lesson/edit.php @@ -1,310 +1,72 @@ . + /** * Provides the interface for overall authoring of lessons * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once('../../config.php'); - require_once('locallib.php'); - require_once('lib.php'); - - $id = required_param('id', PARAM_INT); // Course Module ID - $display = optional_param('display', 0, PARAM_INT); - $mode = optional_param('mode', get_user_preferences('lesson_view', 'collapsed'), PARAM_ALPHA); - $pageid = optional_param('pageid', 0, PARAM_INT); - - if ($mode != 'single') { - set_user_preference('lesson_view', $mode); - } - - list($cm, $course, $lesson) = lesson_get_basics($id); - - if ($firstpage = $DB->get_record('lesson_pages', array('lessonid' => $lesson->id, 'prevpageid' => 0))) { - if (!$pages = $DB->get_records('lesson_pages', array('lessonid' => $lesson->id))) { - print_error('cannotfindrecords', 'lesson'); - } - } - - if ($pageid) { - if (!$singlepage = $DB->get_record('lesson_pages', array('id' => $pageid))) { - print_error('invalidpageid', 'lesson'); - } - } - - require_login($course->id, false, $cm); - - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/edit.php', array('id'=>$id,'mode'=>$mode)); - if ($display !== 0) { - $url->param('display', $display); - } - if ($pageid !== 0) { - $url->param('pageid', $pageid); - } - $PAGE->set_url($url); - $PAGE->navbar->add(get_string('edit')); - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - require_capability('mod/lesson:manage', $context); - - lesson_print_header($cm, $course, $lesson, $mode); - - if (empty($firstpage)) { - // There are no pages; give teacher some options - if (has_capability('mod/lesson:edit', $context)) { - echo $OUTPUT->box( "\n
".get_string("whatdofirst", "lesson")."
". - "id&pageid=0\">". - get_string("importquestions", "lesson")."
". - "id&pageid=0\">". - get_string("importppt", "lesson")."
". - "id&action=addbranchtable&pageid=0&firstpage=1\">". - get_string("addabranchtable", "lesson")."
". - "id&action=addpage&pageid=0&firstpage=1\">". - get_string("addaquestionpage", "lesson"). - "
\n", 'center', '20%'); - } - } else { - // Set some standard variables - $pageid = $firstpage->id; - $prevpageid = 0; - $npages = count($pages); - - switch ($mode) { - case 'collapsed': - $table = new html_table(); - $table->head = array(get_string('pagetitle', 'lesson'), get_string('qtype', 'lesson'), get_string('jumps', 'lesson'), get_string('actions', 'lesson')); - $table->align = array('left', 'left', 'left', 'center'); - $table->wrap = array('', 'nowrap', '', 'nowrap'); - $table->tablealign = 'center'; - $table->cellspacing = 0; - $table->cellpadding = '2px'; - $table->data = array(); - - while ($pageid != 0) { - $page = $pages[$pageid]; - - if ($page->qtype == LESSON_MATCHING) { - // The jumps for matching question type is stored - // in the 3rd and 4rth answer record. - $limitfrom = $limitnum = 2; - } else { - $limitfrom = $limitnum = ''; - } - - $jumps = array(); - $params = array ("lessonid" => $lesson->id, "pageid" => $pageid); - if($answers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid and pageid = :pageid", $params, 'id', '*', $limitfrom, $limitnum)) { - foreach ($answers as $answer) { - $jumps[] = lesson_get_jump_name($answer->jumpto); - } - } - - $table->data[] = array("wwwroot/mod/lesson/edit.php?id=$cm->id&mode=single&pageid=".$page->id."\">".format_string($pages[$pageid]->title,true).'', - lesson_get_qtype_name($page->qtype), - implode("
\n", $jumps), - lesson_print_page_actions($cm->id, $page, $npages, true, true) - ); - $pageid = $page->nextpageid; - } - - echo $OUTPUT->table($table); - break; - - case 'single': - // Only viewing a single page in full - change some variables to display just one - $prevpageid = $singlepage->prevpageid; - $pageid = $singlepage->id; - - $pages = array(); - $pages[$singlepage->id] = $singlepage; - - case 'full': - echo ' - - - '; - - while ($pageid != 0) { - $page = $pages[$pageid]; - - echo "\n"; - break; - } - - $prevpageid = $page->id; - $pageid = $page->nextpageid; - echo ""; - } - echo "
'; - lesson_print_add_links($cm->id, $prevpageid); - echo '
\n"; - echo "\n"; - echo "\n"; - // get the answers in a set order, the id order - if ($answers = $DB->get_records("lesson_answers", array("pageid" => $page->id), "id")) { - echo "\n"; - $i = 1; - $n = 0; - $options = new stdClass; - $options->noclean = true; - $options->para = false; - foreach ($answers as $answer) { - switch ($page->qtype) { - case LESSON_MULTICHOICE: - case LESSON_TRUEFALSE: - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - echo "\n"; - echo "\n"; - break; - case LESSON_MATCHING: - if ($n < 2) { - if ($answer->answer != NULL) { - if ($n == 0) { - echo "\n"; - } else { - echo "\n"; - } - } - $n++; - $i--; - } else { - echo "\n"; - echo "\n"; - } - break; - case LESSON_BRANCHTABLE: - echo "\n"; - break; - } - - $jumptitle = lesson_get_jump_name($answer->jumpto); - if ($page->qtype == LESSON_MATCHING) { - if ($i == 1) { - echo "\n"; - echo "\n"; - } elseif ($i == 2) { - echo "\n"; - echo "\n"; - } - } else { - if ($lesson->custom and - $page->qtype != LESSON_BRANCHTABLE and - $page->qtype != LESSON_ENDOFBRANCH and - $page->qtype != LESSON_CLUSTER and - $page->qtype != LESSON_ENDOFCLUSTER) { - echo "\n"; - } - echo "\n"; - } - $i++; - } - } - echo "
".format_string($page->title)."  \n"; - lesson_print_page_actions($cm->id, $page, $npages); - echo "
\n"; - $options = new stdClass; - $options->noclean = true; - echo format_text($page->contents, FORMAT_MOODLE, $options); - echo "
\n"; - echo lesson_get_qtype_name($page->qtype); - switch ($page->qtype) { - case LESSON_SHORTANSWER : - if ($page->qoption) { - echo " - ".get_string("casesensitive", "lesson"); - } - break; - case LESSON_MULTICHOICE : - if ($page->qoption) { - echo " - ".get_string("multianswer", "lesson"); - } - break; - case LESSON_MATCHING : - echo get_string("firstanswershould", "lesson"); - break; - } - echo "
\n"; - if ($lesson->custom) { - // if the score is > 0, then it is correct - if ($answer->score > 0) { - echo ''.get_string("answer", "lesson")." $i: \n"; - } else { - echo ''.get_string("answer", "lesson")." $i: \n"; - } - } else { - if (lesson_iscorrect($page->id, $answer->jumpto)) { - // underline correct answers - echo ''.get_string("answer", "lesson")." $i: \n"; - } else { - echo ''.get_string("answer", "lesson")." $i: \n"; - } - } - echo "\n"; - echo format_text($answer->answer, FORMAT_MOODLE, $options); - echo "
".get_string("response", "lesson")." $i: \n"; - echo "\n"; - echo format_text($answer->response, FORMAT_MOODLE, $options); - echo "
".get_string("correctresponse", "lesson").": \n"; - echo "\n"; - echo format_text($answer->answer, FORMAT_MOODLE, $options); - echo "
".get_string("wrongresponse", "lesson").": \n"; - echo "\n"; - echo format_text($answer->answer, FORMAT_MOODLE, $options); - echo "
\n"; - if ($lesson->custom) { - // if the score is > 0, then it is correct - if ($answer->score > 0) { - echo ''.get_string("answer", "lesson")." $i: \n"; - } else { - echo ''.get_string("answer", "lesson")." $i: \n"; - } - } else { - if (lesson_iscorrect($page->id, $answer->jumpto)) { - // underline correct answers - echo ''.get_string("answer", "lesson")." $i: \n"; - } else { - echo ''.get_string("answer", "lesson")." $i: \n"; - } - } - echo "\n"; - echo format_text($answer->answer, FORMAT_MOODLE, $options); - echo "
".get_string("matchesanswer", "lesson")." $i: \n"; - echo "\n"; - echo format_text($answer->response, FORMAT_MOODLE, $options); - echo "
\n"; - echo ''.get_string("description", "lesson")." $i: \n"; - echo "\n"; - echo format_text($answer->answer, FORMAT_MOODLE, $options); - echo "
".get_string("correctanswerscore", "lesson"); - echo ": \n"; - echo "$answer->score
".get_string("correctanswerjump", "lesson"); - echo ":\n"; - echo "$jumptitle
".get_string("wronganswerscore", "lesson"); - echo ": \n"; - echo "$answer->score
".get_string("wronganswerjump", "lesson"); - echo ": \n"; - echo "$jumptitle
".get_string("score", "lesson")." $i"; - echo ": \n"; - echo "$answer->score
".get_string("jump", "lesson")." $i"; - echo ": \n"; - echo "$jumptitle
"; - lesson_print_add_links($cm->id, $page->id); - echo "
\n"; - // check the prev links - fix (silently) if necessary - there was a bug in - // versions 1 and 2 when add new pages. Not serious then as the backwards - // links were not used in those versions - if ($page->prevpageid != $prevpageid) { - // fix it - $DB->set_field("lesson_pages", "prevpageid", $prevpageid, array("id" => $page->id)); - debugging("

***prevpageid of page $page->id set to $prevpageid***"); - } - - if (count($pages) == 1) { - echo "

"; - break; - } +require_once('../../config.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); + +try { + $cm = get_coursemodule_from_id('lesson', required_param('id', PARAM_INT), 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:manage', $context); + +$mode = optional_param('mode', get_user_preferences('lesson_view', 'collapsed'), PARAM_ALPHA); +$PAGE->set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/edit.php', array('id'=>$cm->id,'mode'=>$mode))); + +if ($mode != get_user_preferences('lesson_view', 'collapsed') && $mode !== 'single') { + set_user_preference('lesson_view', $mode); +} + +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); +$PAGE->navbar->add(get_string('edit')); +echo $lessonoutput->header($lesson, $mode); +if (!$lesson->has_pages()) { + // There are no pages; give teacher some options + require_capability('mod/lesson:edit', $context); + echo $lessonoutput->add_first_page_links($lesson); +} else { + switch ($mode) { + case 'collapsed': + echo $lessonoutput->display_edit_collapsed($lesson, $lesson->firstpageid); + break; + case 'single': + $pageid = required_param('pageid', PARAM_INT); + $PAGE->url->param('pageid', $pageid); + $singlepage = $lesson->load_page($pageid); + echo $lessonoutput->display_edit_full($lesson, $singlepage->id, $singlepage->prevpageid, true); + break; + case 'full': + echo $lessonoutput->display_edit_full($lesson, $lesson->firstpageid, 0); + break; } +} - echo $OUTPUT->footer(); - +echo $lessonoutput->footer(); \ No newline at end of file diff --git a/mod/lesson/editpage.php b/mod/lesson/editpage.php new file mode 100644 index 0000000000..b79b2aa3df --- /dev/null +++ b/mod/lesson/editpage.php @@ -0,0 +1,104 @@ +. + +/** + * Action for adding a question page. Prints an HTML form. + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +require_once("../../config.php"); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once('editpage_form.php'); + +// first get the preceeding page +$pageid = required_param('pageid', PARAM_INT); +$id = required_param('id', PARAM_INT); // Course Module ID +$qtype = optional_param('qtype', 0, PARAM_INT); +$edit = optional_param('edit', false, PARAM_BOOL); + +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:edit', $context); + +$PAGE->set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('pageid'=>$pageid, 'id'=>$id, 'qtype'=>$qtype))); + +if ($edit) { + $editpage = lesson_page::load($pageid, $lesson); + $qtype = $editpage->qtype; + $edit = true; +} else { + $edit = false; +} + +$jumpto = lesson_page::get_jumptooptions($pageid, $lesson); +$manager = lesson_page_type_manager::get($lesson); +$mform = $manager->get_page_form($qtype, array('editoroptions'=>null, 'jumpto'=>$jumpto, 'lesson'=>$lesson, 'edit'=>$edit, 'maxbytes'=>$PAGE->course->maxbytes)); + +if ($edit) { + $properties = $editpage->properties(); + $properties->pageid = $editpage->id; + $properties->id = $cm->id; + $mform->set_data($properties, $context, $editpage->id); + $PAGE->navbar->add(get_string('edit'), new moodle_url($CFG->wwwroot.'/mod/lesson/edit.php', array('id'=>$id))); + $PAGE->navbar->add(get_string('editingquestionpage', 'lesson', get_string($mform->qtypestring, 'lesson'))); +} else { + // Give the page type being created a chance to override the creation process + // this is used by endofbranch, cluster, and endofcluster to skip the creation form. + // IT SHOULD ALWAYS CALL require_sesskey(); + $mform->construction_override($pageid, $lesson); + + $defaultpage = new stdClass; + $defaultpage->id = $cm->id; + $defaultpage->pageid = $pageid; + $defaultpage->qtype = $qtype; + $defaultpage->contentsformat = FORMAT_HTML; + $mform->set_data($defaultpage); + $PAGE->navbar->add(get_string('addanewpage', 'lesson'), $PAGE->url); + if ($qtype !== 'unknown') { + $PAGE->navbar->add(get_string($mform->qtypestring, 'lesson')); + } +} + +if ($data = $mform->get_data()) { + require_sesskey(); + if ($edit) { + $data->lessonid = $data->id; + $data->id = $data->pageid; + unset($data->pageid); + unset($data->edit); + $editpage->update($data, $context, $PAGE->course->maxbytes); + } else { + $editpage = lesson_page::create($data, $lesson, $context, $PAGE->course->maxbytes); + } + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/edit.php', array('id'=>$cm->id))); +} + +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); +echo $lessonoutput->header($lesson); +$mform->display(); +echo $lessonoutput->footer(); \ No newline at end of file diff --git a/mod/lesson/editpage_form.php b/mod/lesson/editpage_form.php new file mode 100644 index 0000000000..7777447eed --- /dev/null +++ b/mod/lesson/editpage_form.php @@ -0,0 +1,57 @@ +. + +/** + * Generic forms used for page selection + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * Question selection form + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ +class lesson_add_page_form_selection extends lesson_add_page_form_base { + + public $qtype = 'questiontype'; + public $qtypestring = 'selectaqtype'; + protected $standard = false; + protected $manager = null; + + public function __construct($arg1, $arg2) { + $this->manager = lesson_page_type_manager::get($arg2['lesson']); + parent::__construct($arg1, $arg2); + } + + public function custom_definition() { + $mform = $this->_form; + $types = $this->manager->get_page_type_strings(lesson_page::TYPE_QUESTION); + asort($types); + $mform->addElement('select', 'qtype', get_string('selectaqtype', 'lesson'), $types); + $mform->setHelpButton('qtype', array('questiontypes', get_string("questiontype", "lesson"), "lesson")); + } +} + +/** + * Dummy class to represent an unknown question type and direct to the selection + * form. + */ +final class lesson_add_page_form_unknown extends lesson_add_page_form_base {} \ No newline at end of file diff --git a/mod/lesson/essay.php b/mod/lesson/essay.php index 9bff13759a..45aed8c6ae 100644 --- a/mod/lesson/essay.php +++ b/mod/lesson/essay.php @@ -1,390 +1,392 @@ . + /** * Provides the interface for grading essay questions * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once('../../config.php'); - require_once('locallib.php'); - require_once('lib.php'); - require_once($CFG->libdir.'/eventslib.php'); - - $id = required_param('id', PARAM_INT); // Course Module ID - $mode = optional_param('mode', 'display', PARAM_ALPHA); - - list($cm, $course, $lesson) = lesson_get_basics($id); - - require_login($course->id, false, $cm); - - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$id)); - if ($mode !== 'display') { - $url->param('mode', $mode); - } - $PAGE->set_url($url); - $PAGE->navbar->add(get_string('manualgrading','lesson')); - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - require_capability('mod/lesson:edit', $context); +require_once('../../config.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once($CFG->dirroot.'/mod/lesson/essay_form.php'); +require_once($CFG->libdir.'/eventslib.php'); + +$id = required_param('id', PARAM_INT); // Course Module ID +$mode = optional_param('mode', 'display', PARAM_ALPHA); +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:edit', $context); + +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$id)); +if ($mode !== 'display') { + $url->param('mode', $mode); +} +$PAGE->set_url($url); +$PAGE->navbar->add(get_string('manualgrading','lesson')); /// Handle any preprocessing before header is printed - based on $mode - switch ($mode) { - case 'display': // Default view - get the necessary data - // Get lesson pages that are essay - $params = array ("lessonid" => $lesson->id, "qtype" => LESSON_ESSAY); - if ($pages = $DB->get_records_select('lesson_pages', "lessonid = :lessonid AND qtype = :qtype", $params)) { - // Get only the attempts that are in response to essay questions - list($usql, $parameters) = $DB->get_in_or_equal(array_keys($pages)); - if ($essayattempts = $DB->get_records_select('lesson_attempts', 'pageid $usql', $parameters)) { - // Get all the users who have taken this lesson, order by their last name - if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) { - $params["groupinid"] = $cm->groupingid; - $sql = "SELECT DISTINCT u.* - FROM {lesson_attempts} a - INNER JOIN {user} u ON u.id = a.userid - INNER JOIN {groups_members} gm ON gm.userid = u.id - INNER JOIN {groupings_groups} gg ON gm.groupid = :groupinid - WHERE a.lessonid = :lessonid - ORDER BY u.lastname"; - } else { - $sql = "SELECT u.* - FROM {user} u, - {lesson_attempts} a - WHERE a.lessonid = :lessonid and - u.id = a.userid - ORDER BY u.lastname"; - } - if (!$users = $DB->get_records_sql($sql, $params)) { - $mode = 'none'; // not displaying anything - lesson_set_message(get_string('noonehasanswered', 'lesson')); - } - } else { - $mode = 'none'; // not displaying anything - lesson_set_message(get_string('noonehasanswered', 'lesson')); - } - } else { - $mode = 'none'; // not displaying anything - lesson_set_message(get_string('noessayquestionsfound', 'lesson')); +switch ($mode) { + case 'grade': + // Grading form - get the necessary data + require_sesskey(); + + $attemptid = required_param('attemptid', PARAM_INT); + + if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid))) { + print_error('cannotfindattempt', 'lesson'); + } + $page = $lesson->load_page($attempt->pageid); + if (!$user = $DB->get_record('user', array('id' => $attempt->userid))) { + print_error('cannotfinduser', 'lesson'); + } + if (!$answer = $DB->get_record('lesson_answers', array('lessonid' => $lesson->id, 'pageid' => $page->id))) { + print_error('cannotfindanswer', 'lesson'); + } + break; + + case 'update': + require_sesskey(); + $mform = new essay_grading_form(); + if ($form = $mform->get_data()) { + + if (optional_param('cancel', false, PARAM_RAW)) { + redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id"); } - break; - case 'grade': // Grading form - get the necessary data - require_sesskey(); $attemptid = required_param('attemptid', PARAM_INT); - if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid))) { print_error('cannotfindattempt', 'lesson'); } - if (!$page = $DB->get_record('lesson_pages', array('id' => $attempt->pageid))) { - print_error('cannotfindpages', 'lesson'); + if (!$grades = $DB->get_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$attempt->userid), 'completed', '*', $attempt->retry, 1)) { + print_error('cannotfindgrade', 'lesson'); } - if (!$user = $DB->get_record('user', array('id' => $attempt->userid))) { - print_error('cannotfinduser', 'lesson'); - } - if (!$answer = $DB->get_record('lesson_answers', array('lessonid' => $lesson->id, 'pageid' => $page->id))) { - print_error('cannotfindanswer', 'lesson'); - } - break; - case 'update': - if (confirm_sesskey() and $form = data_submitted()) { - if (optional_param('cancel', 0, PARAM_RAW)) { - redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id"); - } - - $attemptid = required_param('attemptid', PARAM_INT); - if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid))) { - print_error('cannotfindattempt', 'lesson'); - } - $params = array ("lessonid" => $lesson->id, "userid" => $attempt->userid); - if (!$grades = $DB->get_records_select('lesson_grades', "lessonid = :lessonid and userid = :userid", $params, 'completed', '*', $attempt->retry, 1)) { - print_error('cannotfindgrade', 'lesson'); - } + $essayinfo = new stdClass; + $essayinfo = unserialize($attempt->useranswer); - $essayinfo = new stdClass; - $essayinfo = unserialize($attempt->useranswer); + $essayinfo->graded = 1; + $essayinfo->score = clean_param($form->score, PARAM_INT); + $essayinfo->response = clean_param($form->response, PARAM_RAW); + $essayinfo->sent = 0; + if (!$lesson->custom && $essayinfo->score == 1) { + $attempt->correct = 1; + } else { + $attempt->correct = 0; + } - $essayinfo->graded = 1; - $essayinfo->score = clean_param($form->score, PARAM_INT); - $essayinfo->response = clean_param($form->response, PARAM_RAW); - $essayinfo->sent = 0; - if (!$lesson->custom && $essayinfo->score == 1) { - $attempt->correct = 1; - } else { - $attempt->correct = 0; - } + $attempt->useranswer = serialize($essayinfo); - $attempt->useranswer = serialize($essayinfo); + $DB->update_record('lesson_attempts', $attempt); - $DB->update_record('lesson_attempts', $attempt); + // Get grade information + $grade = current($grades); + $gradeinfo = lesson_grade($lesson, $attempt->retry, $attempt->userid); - // Get grade information - $grade = current($grades); - $gradeinfo = lesson_grade($lesson, $attempt->retry, $attempt->userid); + // Set and update + $updategrade->id = $grade->id; + $updategrade->grade = $gradeinfo->grade; + $DB->update_record('lesson_grades', $updategrade); + // Log it + add_to_log($course->id, 'lesson', 'update grade', "essay.php?id=$cm->id", $lesson->name, $cm->id); - // Set and update - $updategrade->id = $grade->id; - $updategrade->grade = $gradeinfo->grade; - $DB->update_record('lesson_grades', $updategrade); - // Log it - add_to_log($course->id, 'lesson', 'update grade', "essay.php?id=$cm->id", $lesson->name, $cm->id); + $lesson->add_message(get_string('changessaved'), 'notifysuccess'); - lesson_set_message(get_string('changessaved'), 'notifysuccess'); + // update central gradebook + lesson_update_grades($lesson, $grade->userid); - // update central gradebook - lesson_update_grades($lesson, $grade->userid); + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$cm->id))); + } else { + print_error('invalidformdata'); + } + break; + case 'email': + // Sending an email(s) to a single user or all + require_sesskey(); - redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id"); - } else { - print_error('invalidformdata'); + // Get our users (could be singular) + if ($userid = optional_param('userid', 0, PARAM_INT)) { + $queryadd = " AND userid = ?"; + if (! $users = $DB->get_records('user', array('id' => $userid))) { + print_error('cannotfinduser', 'lesson'); } - break; - case 'email': // Sending an email(s) to a single user or all - require_sesskey(); - - // Get our users (could be singular) - if ($userid = optional_param('userid', 0, PARAM_INT)) { - $queryadd = " AND userid = :userid"; - if (! $users = $DB->get_records('user', array('id' => $userid))) { - print_error('cannotfinduser', 'lesson'); - } - } else { - $queryadd = ''; - $params = array ("lessonid" => $lesson->id); - if (!$users = $DB->get_records_sql("SELECT u.* - FROM {user} u, - {lesson_attempts} a - WHERE a.lessonid = :lessonid and - u.id = a.userid - ORDER BY u.lastname", $params)) { - print_error('cannotfinduser', 'lesson'); - } + } else { + $queryadd = ''; + $params = array ("lessonid" => $lesson->id); + if (!$users = $DB->get_records_sql("SELECT DISTINCT u.id, u.* + FROM {user} u, + {lesson_attempts} a + WHERE a.lessonid = :lessonid and + u.id = a.userid + ORDER BY u.lastname", $params)) { + print_error('cannotfinduser', 'lesson'); } + } - // Get lesson pages that are essay - $params = array ("lessonid" => $lesson->id, "qtype" => LESSON_ESSAY); - if (!$pages = $DB->get_records_select('lesson_pages', "lessonid = :lessonid AND qtype = :qtype", $params)) { - print_error('cannotfindpages', 'lesson'); + $pages = $lesson->load_all_pages(); + foreach ($pages as $key=>$page) { + if ($page->qtype !== LESSON_PAGE_ESSAY) { + unset($pages[$key]); } + } + + // Get only the attempts that are in response to essay questions + list($usql, $params) = $DB->get_in_or_equal(array_keys($pages)); + if (!empty($queryadd)) { + $params[] = $userid; + } + if (!$attempts = $DB->get_records_select('lesson_attempts', "pageid $usql".$queryadd, $params)) { + print_error('nooneansweredthisquestion', 'lesson'); + } + // Get the answers + list($answerUsql, $parameters) = $DB->get_in_or_equal(array_keys($pages)); + array_unshift($parameters, $lesson->id); + if (!$answers = $DB->get_records_select('lesson_answers', "lessonid = ? AND pageid $answerUsql", $parameters, '', 'pageid, score')) { + print_error('cannotfindanswer', 'lesson'); + } + $options = new stdClass; + $options->noclean = true; + + foreach ($attempts as $attempt) { + $essayinfo = unserialize($attempt->useranswer); + if ($essayinfo->graded && !$essayinfo->sent) { + // Holds values for the essayemailsubject string for the email message + $a = new stdClass; + + // Set the grade + $grades = $DB->get_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$attempt->userid), 'completed', '*', $attempt->retry, 1); + $grade = current($grades); + $a->newgrade = $grade->grade; + + // Set the points + if ($lesson->custom) { + $a->earned = $essayinfo->score; + $a->outof = $answers[$attempt->pageid]->score; + } else { + $a->earned = $essayinfo->score; + $a->outof = 1; + } - // Get only the attempts that are in response to essay questions - list($usql, $params) = $DB->get_in_or_equal(array_keys($pages)); - if (isset($queryadd) && $queryadd!='') { - $params["userid"] = $userid; + // Set rest of the message values + $currentpage = $lesson->load_page($attempt->pageid); + $a->question = format_text($currentpage->contents, FORMAT_MOODLE, $options); + $a->response = s($essayinfo->answer); + $a->comment = s($essayinfo->response); + + // Fetch message HTML and plain text formats + $message = get_string('essayemailmessage2', 'lesson', $a); + $plaintext = format_text_email($message, FORMAT_HTML); + + // Subject + $subject = get_string('essayemailsubject', 'lesson', format_string($pages[$attempt->pageid]->title,true)); + + $eventdata = new object(); + $eventdata->modulename = 'lesson'; + $eventdata->userfrom = $USER; + $eventdata->userto = $users[$attempt->userid]; + $eventdata->subject = $subject; + $eventdata->fullmessage = $plaintext; + $eventdata->fullmessageformat = FORMAT_PLAIN; + $eventdata->fullmessagehtml = $message; + $eventdata->smallmessage = ''; + + // Required for messaging framework + $eventdata->component = 'mod_lesson'; + $eventdata->name = 'graded_essay'; + + message_send($eventdata); + $essayinfo->sent = 1; + $attempt->useranswer = serialize($essayinfo); + $DB->update_record('lesson_attempts', $attempt); + // Log it + add_to_log($course->id, 'lesson', 'update email essay grade', "essay.php?id=$cm->id", format_string($pages[$attempt->pageid]->title,true).': '.fullname($users[$attempt->userid]), $cm->id); } - if (!$attempts = $DB->get_records_select('lesson_attempts', "pageid $usql".$queryadd, $params)) { - print_error('nooneansweredthisquestion', 'lesson'); + } + $lesson->add_message(get_string('emailsuccess', 'lesson'), 'notifysuccess'); + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$cm->id))); + break; + case 'display': // Default view - get the necessary data + default: + // Get lesson pages that are essay + $pages = $lesson->load_all_pages(); + foreach ($pages as $key=>$page) { + if ($page->qtype !== LESSON_PAGE_ESSAY) { + unset($pages[$key]); } - // Get the answers - list($answerUsql, $parameters) = $DB->get_in_or_equal(array_keys($pages)); - $parameters["lessonid"] = $lesson->id; - if (!$answers = $DB->get_records_select('lesson_answers', "lessonid = :lessonid AND pageid $answerUsql", $parameters, '', 'pageid, score')) { - print_error('cannotfindanswer', 'lesson'); + } + if (count($pages) > 0) { + $params = array ("lessonid" => $lesson->id, "qtype" => LESSON_PAGE_ESSAY); + // Get only the attempts that are in response to essay questions + list($usql, $parameters) = $DB->get_in_or_equal(array_keys($pages)); + if ($essayattempts = $DB->get_records_select('lesson_attempts', 'pageid '.$usql, $parameters)) { + // Get all the users who have taken this lesson, order by their last name + if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) { + $params["groupinid"] = $cm->groupingid; + $sql = "SELECT DISTINCT u.* + FROM {lesson_attempts} a + INNER JOIN {user} u ON u.id = a.userid + INNER JOIN {groups_members} gm ON gm.userid = u.id + INNER JOIN {groupings_groups} gg ON gm.groupid = :groupinid + WHERE a.lessonid = :lessonid + ORDER BY u.lastname"; + } else { + $sql = "SELECT DISTINCT u.* + FROM {user} u, + {lesson_attempts} a + WHERE a.lessonid = :lessonid and + u.id = a.userid + ORDER BY u.lastname"; + } + if (!$users = $DB->get_records_sql($sql, $params)) { + $mode = 'none'; // not displaying anything + $lesson->add_message(get_string('noonehasanswered', 'lesson')); + } + } else { + $mode = 'none'; // not displaying anything + $lesson->add_message(get_string('noonehasanswered', 'lesson')); } - $options = new stdClass; - $options->noclean = true; - - foreach ($attempts as $attempt) { - $essayinfo = unserialize($attempt->useranswer); - if ($essayinfo->graded and !$essayinfo->sent) { - // Holds values for the essayemailsubject string for the email message - $a = new stdClass; - - // Set the grade - $params = array ("lessonid" => $lesson->id, "userid" => $attempt->userid); - $grades = $DB->get_records_select('lesson_grades', "lessonid = :lessonid and userid = :userid", $params, 'completed', '*', $attempt->retry, 1); - $grade = current($grades); - $a->newgrade = $grade->grade; - - // Set the points - if ($lesson->custom) { - $a->earned = $essayinfo->score; - $a->outof = $answers[$attempt->pageid]->score; + } else { + $mode = 'none'; // not displaying anything + $lesson->add_message(get_string('noessayquestionsfound', 'lesson')); + } + break; +} +// Log it +add_to_log($course->id, 'lesson', 'view grade', "essay.php?id=$cm->id", get_string('manualgrading', 'lesson'), $cm->id); + +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); +echo $lessonoutput->header($lesson, 'essay'); + +switch ($mode) { + case 'display': + // Expects $user, $essayattempts and $pages to be set already + + // Group all the essays by userid + $studentessays = array(); + foreach ($essayattempts as $essay) { + // Not very nice :) but basically + // this organizes the essays so we know how many + // times a student answered an essay per try and per page + $studentessays[$essay->userid][$essay->pageid][$essay->retry][] = $essay; + } + + // Setup table + $table = new html_table(); + $table->head = array(get_string('name'), get_string('essays', 'lesson'), get_string('email', 'lesson')); + $table->set_classes(array('standardtable', 'generaltable')); + $table->align = array('left', 'left', 'left'); + $table->wrap = array('nowrap', 'nowrap', ''); + + // Cycle through all the students + foreach (array_keys($studentessays) as $userid) { + $studentname = fullname($users[$userid], true); + $essaylinks = array(); + + // Number of attempts on the lesson + $attempts = $DB->count_records('lesson_grades', array('userid'=>$userid, 'lessonid'=>$lesson->id)); + + // Go through each essay page + foreach ($studentessays[$userid] as $page => $tries) { + $count = 0; + + // Go through each attempt per page + foreach($tries as $try) { + if ($count == $attempts) { + break; // Stop displaying essays (attempt not completed) + } + $count++; + + // Make sure they didn't answer it more than the max number of attmepts + if (count($try) > $lesson->maxattempts) { + $essay = $try[$lesson->maxattempts-1]; } else { - $a->earned = $essayinfo->score; - $a->outof = 1; + $essay = end($try); } - // Set rest of the message values - $a->question = format_text($pages[$attempt->pageid]->contents, FORMAT_MOODLE, $options); - $a->response = s($essayinfo->answer); - $a->comment = s($essayinfo->response); - - // Fetch message HTML and plain text formats - $message = get_string('essayemailmessage2', 'lesson', $a); - $plaintxt = format_text_email($message, FORMAT_HTML); - - // Subject - $subject = get_string('essayemailsubject', 'lesson', format_string($pages[$attempt->pageid]->title,true)); - - $eventdata = new object(); - $eventdata->modulename = 'lesson'; - $eventdata->userfrom = $USER; - $eventdata->userto = $users[$attempt->userid]; - $eventdata->subject = $subject; - $eventdata->fullmessage = $plaintext; - $eventdata->fullmessageformat = FORMAT_PLAIN; - $eventdata->fullmessagehtml = $message; - $eventdata->smallmessage = ''; - message_send($eventdata); - $essayinfo->sent = 1; - $attempt->useranswer = serialize($essayinfo); - $DB->update_record('lesson_attempts', $attempt); - // Log it - add_to_log($course->id, 'lesson', 'update email essay grade', "essay.php?id=$cm->id", format_string($pages[$attempt->pageid]->title,true).': '.fullname($users[$attempt->userid]), $cm->id); + // Start processing the attempt + $essayinfo = unserialize($essay->useranswer); + + // link for each essay + $url = new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'grade','attemptid'=>$essay->id,'sesskey'=>sesskey())); + $link = html_link::make($url, userdate($essay->timeseen, get_string('strftimedatetime')).' '.format_string($pages[$essay->pageid]->title,true)); + // Different colors for all the states of an essay (graded, if sent, not graded) + if (!$essayinfo->graded) { + $link->set_classes("graded"); + } elseif (!$essayinfo->sent) { + $link->set_classes("sent"); + } else { + $link->set_classes("ungraded"); + } + $essaylinks[] = $OUTPUT->link($link); } } - lesson_set_message(get_string('emailsuccess', 'lesson'), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id"); - break; - } - - // Log it - add_to_log($course->id, 'lesson', 'view grade', "essay.php?id=$cm->id", get_string('manualgrading', 'lesson'), $cm->id); - - lesson_print_header($cm, $course, $lesson, 'essay'); - - switch ($mode) { - case 'display': - // Expects $user, $essayattempts and $pages to be set already - - // Group all the essays by userid - $studentessays = array(); - foreach ($essayattempts as $essay) { - // Not very nice :) but basically - // this organizes the essays so we know how many - // times a student answered an essay per try and per page - $studentessays[$essay->userid][$essay->pageid][$essay->retry][] = $essay; - } + // email link for this user + $url = new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'email','userid'=>$userid,'sesskey'=>sesskey())); + $emaillink = $OUTPUT->link(html_link::make($url, get_string('emailgradedessays', 'lesson'))); - // Setup table - $table = new html_table(); - $table->head = array(get_string('name'), get_string('essays', 'lesson'), get_string('email', 'lesson')); - $table->align = array('left', 'left', 'left'); - $table->wrap = array('nowrap', 'nowrap', 'nowrap'); - - // Get the student ids of the users who have answered the essay question - $userids = array_keys($studentessays); - - // Cycle through all the students - foreach ($userids as $userid) { - $studentname = fullname($users[$userid], true); - $essaylinks = array(); - - // Number of attempts on the lesson - $attempts = $DB->count_records('lesson_grades', array('userid'=>$userid, 'lessonid'=>$lesson->id)); - - // Go through each essay page - foreach ($studentessays[$userid] as $page => $tries) { - $count = 0; - - // Go through each attempt per page - foreach($tries as $try) { - if ($count == $attempts) { - break; // Stop displaying essays (attempt not completed) - } - $count++; - - // Make sure they didn't answer it more than the max number of attmepts - if (count($try) > $lesson->maxattempts) { - $essay = $try[$lesson->maxattempts-1]; - } else { - $essay = end($try); - } - - // Start processing the attempt - $essayinfo = unserialize($essay->useranswer); - - // Different colors for all the states of an essay (graded, if sent, not graded) - if (!$essayinfo->graded) { - $class = ' class="graded"'; - } elseif (!$essayinfo->sent) { - $class = ' class="sent"'; - } else { - $class = ' class="ungraded"'; - } - // link for each essay - $essaylinks[] = "wwwroot/mod/lesson/essay.php?id=$cm->id&mode=grade&attemptid=$essay->id&sesskey=".sesskey().'">'.userdate($essay->timeseen, get_string('strftimedatetime')).' '.format_string($pages[$essay->pageid]->title,true).''; - } - } - // email link for this user - $emaillink = "wwwroot/mod/lesson/essay.php?id=$cm->id&mode=email&userid=$userid&sesskey=".sesskey().'">'.get_string('emailgradedessays', 'lesson').''; + $table->data[] = array($OUTPUT->user_picture(moodle_user_picture::make($users[$userid], $course->id)).$studentname, implode("
", $essaylinks), $emaillink); + } - $table->data[] = array($OUTPUT->user_picture(moodle_user_picture::make($users[$userid], $course->id)).$studentname, implode("
\n", $essaylinks), $emaillink); - } - // email link for all users - $emailalllink = "wwwroot/mod/lesson/essay.php?id=$cm->id&mode=email&sesskey=".sesskey().'">'.get_string('emailallgradedessays', 'lesson').''; - - $table->data[] = array(' ', ' ', $emailalllink); - - echo $OUTPUT->table($table); - break; - case 'grade': - // Grading form - // Expects the following to be set: $attemptid, $answer, $user, $page, $attempt - - echo '

-
- - - - '; - - // All tables will have these settings - $originaltable = new html_table(); - $originaltable->align = array('left'); - $originaltable->wrap = array(); - $originaltable->width = '50%'; - $originaltable->size = array('100%'); - $originaltable->add_class('generaltable gradetable'); - - // Print the question - $table = clone($originaltable); - $table->head = array(get_string('question', 'lesson')); - $options = new stdClass; - $options->noclean = true; - $table->data[] = array(format_text($page->contents, FORMAT_MOODLE, $options)); - - echo $OUTPUT->table($table); - - // Now the user's answer - $essayinfo = unserialize($attempt->useranswer); + // email link for all users + $url = new moodle_url($CFG->wwwroot.'/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'email','sesskey'=>sesskey())); + $emailalllink = $OUTPUT->link(html_link::make($url, get_string('emailallgradedessays', 'lesson'))); - $table = clone($originaltable); - $table = new html_table(); - $table->head = array(get_string('studentresponse', 'lesson', fullname($user, true))); - $table->data[] = array(s($essayinfo->answer)); - - echo $OUTPUT->table($table); - - // Now a response box and grade drop-down for grader - $table = clone($originaltable); - $table->head = array(get_string('comments', 'lesson')); - $table->data[] = array(print_textarea(false, 15, 60, 0, 0, 'response', $essayinfo->response, $course->id, true)); - $options = array(); - if ($lesson->custom) { - for ($i=$answer->score; $i>=0; $i--) { - $options[$i] = $i; - } - } else { - $options[0] = get_string('nocredit', 'lesson'); - $options[1] = get_string('credit', 'lesson'); - } - $select = html_select::make($options, 'score', $essayinfo->score, false); - $select->nothingvalue = ''; - $table->data[] = array(get_string('essayscore', 'lesson').': '.$OUTPUT->select($select)); - - echo $OUTPUT->table($table); - echo '
- - -
-
-
'; - break; - } - - echo $OUTPUT->footer(); + $table->data[] = array(' ', ' ', $emailalllink); + + echo $OUTPUT->table($table); + break; + case 'grade': + // Grading form + // Expects the following to be set: $attemptid, $answer, $user, $page, $attempt + + $essayinfo = unserialize($attempt->useranswer); + $options = array(); + if ($lesson->custom) { + $i = $answer->score; + while ($i >= 0) { + $options[$i] = (string)$i; + $i--; + } + } else { + $options[0] = get_string('nocredit', 'lesson'); + $options[1] = get_string('credit', 'lesson'); + } + $mform = new essay_grading_form(null, array('scoreoptions'=>$options, 'user'=>$user)); + + $data = new stdClass; + $data->id = $cm->id; + $data->attemptid = $attemptid; + $data->score = $essayinfo->score; + $data->studentanswer = format_string($essayinfo->answer, FORMAT_MOODLE); + $data->response = $essayinfo->response; + $mform->set_data($data); + + $mform->display(); + break; +} + +echo $OUTPUT->footer(); diff --git a/mod/lesson/essay_form.php b/mod/lesson/essay_form.php new file mode 100644 index 0000000000..93c4b9c827 --- /dev/null +++ b/mod/lesson/essay_form.php @@ -0,0 +1,64 @@ +. + +/** + * Essay grading form + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * Include formslib if it has not already been included + */ +require_once($CFG->libdir.'/formslib.php'); + +/** + * Essay grading form + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ +class essay_grading_form extends moodleform { + + public function definition() { + $mform = $this->_form; + + $mform->addElement('header', 'formheader', get_string('question', 'lesson')); + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'attemptid'); + $mform->setType('attemptid', PARAM_INT); + + $mform->addElement('hidden', 'mode', 'update'); + $mform->setType('mode', PARAM_ALPHA); + + $mform->addElement('static', 'studentanswer', get_string('studentresponse', 'lesson', fullname($this->_customdata['user'], true))); + + $mform->addElement('textarea', 'response', get_string('comments', 'lesson'), array('rows'=>'15', 'cols'=>'60')); + $mform->setType('response', PARAM_TEXT); + + $mform->addElement('select', 'score', get_string('essayscore', 'lesson'), $this->_customdata['scoreoptions']); + $mform->setType('score', PARAM_INT); + + $this->add_action_buttons(get_string('cancel'), get_string('savechanges')); + + } +} \ No newline at end of file diff --git a/mod/lesson/format.php b/mod/lesson/format.php index f6647ceeed..35773ed69c 100644 --- a/mod/lesson/format.php +++ b/mod/lesson/format.php @@ -1,31 +1,292 @@ . + /** * format.php - Default format class for file imports/exports. Doesn't do * everything on it's own -- it needs to be extended. * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + * Included by import.ph + * * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * Given some question info and some data about the the answers + * this function parses, organises and saves the question + * + * This is only used when IMPORTING questions and is only called + * from format.php + * Lifted from mod/quiz/lib.php - + * 1. all reference to oldanswers removed + * 2. all reference to quiz_multichoice table removed + * 3. In SHORTANSWER questions usecase is store in the qoption field + * 4. In NUMERIC questions store the range as two answers + * 5. TRUEFALSE options are ignored + * 6. For MULTICHOICE questions with more than one answer the qoption field is true + * + * @param opject $question Contains question data like question, type and answers. + * @return object Returns $result->error or $result->notice. **/ +function lesson_save_question_options($question, $lesson) { + global $DB; + + // These lines are required to ensure that all page types have + // been loaded for the following switch + if (!($lesson instanceof lesson)) { + $lesson = new lesson($lesson); + } + $manager = lesson_page_type_manager::get($lesson); + + $timenow = time(); + switch ($question->qtype) { + case LESSON_PAGE_SHORTANSWER: + + $answers = array(); + $maxfraction = -1; + + // Insert all the new answers + foreach ($question->answer as $key => $dataanswer) { + if ($dataanswer != "") { + $answer = new stdClass; + $answer->lessonid = $question->lessonid; + $answer->pageid = $question->id; + if ($question->fraction[$key] >=0.5) { + $answer->jumpto = LESSON_NEXTPAGE; + } + $answer->timecreated = $timenow; + $answer->grade = $question->fraction[$key] * 100; + $answer->answer = $dataanswer; + $answer->response = $question->feedback[$key]; + $answer->id = $DB->insert_record("lesson_answers", $answer); + $answers[] = $answer->id; + if ($question->fraction[$key] > $maxfraction) { + $maxfraction = $question->fraction[$key]; + } + } + } + + + /// Perform sanity checks on fractional grades + if ($maxfraction != 1) { + $maxfraction = $maxfraction * 100; + $result->notice = get_string("fractionsnomax", "quiz", $maxfraction); + return $result; + } + break; + + case LESSON_PAGE_NUMERICAL: // Note similarities to SHORTANSWER + + $answers = array(); + $maxfraction = -1; + + + // for each answer store the pair of min and max values even if they are the same + foreach ($question->answer as $key => $dataanswer) { + if ($dataanswer != "") { + $answer = new stdClass; + $answer->lessonid = $question->lessonid; + $answer->pageid = $question->id; + $answer->jumpto = LESSON_NEXTPAGE; + $answer->timecreated = $timenow; + $answer->grade = $question->fraction[$key] * 100; + $min = $question->answer[$key] - $question->tolerance[$key]; + $max = $question->answer[$key] + $question->tolerance[$key]; + $answer->answer = $min.":".$max; + // $answer->answer = $question->min[$key].":".$question->max[$key]; original line for min/max + $answer->response = $question->feedback[$key]; + $answer->id = $DB->insert_record("lesson_answers", $answer); + + $answers[] = $answer->id; + if ($question->fraction[$key] > $maxfraction) { + $maxfraction = $question->fraction[$key]; + } + } + } + + /// Perform sanity checks on fractional grades + if ($maxfraction != 1) { + $maxfraction = $maxfraction * 100; + $result->notice = get_string("fractionsnomax", "quiz", $maxfraction); + return $result; + } + break; + + + case LESSON_PAGE_TRUEFALSE: + + // the truth + $answer->lessonid = $question->lessonid; + $answer->pageid = $question->id; + $answer->timecreated = $timenow; + $answer->answer = get_string("true", "quiz"); + $answer->grade = $question->answer * 100; + if ($answer->grade > 50 ) { + $answer->jumpto = LESSON_NEXTPAGE; + } + if (isset($question->feedbacktrue)) { + $answer->response = $question->feedbacktrue; + } + $true->id = $DB->insert_record("lesson_answers", $answer); + + // the lie + $answer = new stdClass; + $answer->lessonid = $question->lessonid; + $answer->pageid = $question->id; + $answer->timecreated = $timenow; + $answer->answer = get_string("false", "quiz"); + $answer->grade = (1 - (int)$question->answer) * 100; + if ($answer->grade > 50 ) { + $answer->jumpto = LESSON_NEXTPAGE; + } + if (isset($question->feedbackfalse)) { + $answer->response = $question->feedbackfalse; + } + $false->id = $DB->insert_record("lesson_answers", $answer); + + break; + + case LESSON_PAGE_MULTICHOICE: + + $totalfraction = 0; + $maxfraction = -1; + + $answers = array(); + + // Insert all the new answers + foreach ($question->answer as $key => $dataanswer) { + if ($dataanswer != "") { + $answer = new stdClass; + $answer->lessonid = $question->lessonid; + $answer->pageid = $question->id; + $answer->timecreated = $timenow; + $answer->grade = $question->fraction[$key] * 100; + // changed some defaults + /* Original Code + if ($answer->grade > 50 ) { + $answer->jumpto = LESSON_NEXTPAGE; + } + Replaced with: */ + if ($answer->grade > 50 ) { + $answer->jumpto = LESSON_NEXTPAGE; + $answer->score = 1; + } + // end Replace + $answer->answer = $dataanswer; + $answer->response = $question->feedback[$key]; + $answer->id = $DB->insert_record("lesson_answers", $answer); + // for Sanity checks + if ($question->fraction[$key] > 0) { + $totalfraction += $question->fraction[$key]; + } + if ($question->fraction[$key] > $maxfraction) { + $maxfraction = $question->fraction[$key]; + } + } + } + + /// Perform sanity checks on fractional grades + if ($question->single) { + if ($maxfraction != 1) { + $maxfraction = $maxfraction * 100; + $result->notice = get_string("fractionsnomax", "quiz", $maxfraction); + return $result; + } + } else { + $totalfraction = round($totalfraction,2); + if ($totalfraction != 1) { + $totalfraction = $totalfraction * 100; + $result->notice = get_string("fractionsaddwrong", "quiz", $totalfraction); + return $result; + } + } + break; + + case LESSON_PAGE_MATCHING: + + $subquestions = array(); + + $defaultanswer = new stdClass; + $defaultanswer->lessonid = $question->lessonid; + $defaultanswer->pageid = $question->id; + $defaultanswer->timecreated = $timenow; + $defaultanswer->grade = 0; + + // The first answer should always be the correct answer + $correctanswer = clone($defaultanswer); + $correctanswer->answer = get_string('thatsthecorrectanswer', 'lesson'); + $DB->insert_record("lesson_answers", $correctanswer); + + // The second answer should always be the wrong answer + $wronganswer = clone($defaultanswer); + $wronganswer->answer = get_string('thatsthewronganswer', 'lesson'); + $DB->insert_record("lesson_answers", $wronganswer); + + $i = 0; + // Insert all the new question+answer pairs + foreach ($question->subquestions as $key => $questiontext) { + $answertext = $question->subanswers[$key]; + if (!empty($questiontext) and !empty($answertext)) { + $answer = clone($defaultanswer); + $answer->answer = $questiontext; + $answer->response = $answertext; + if ($i == 0) { + // first answer contains the correct answer jump + $answer->jumpto = LESSON_NEXTPAGE; + } + $subquestion->id = $DB->insert_record("lesson_answers", $answer); + $subquestions[] = $subquestion->id; + $i++; + } + } + + if (count($subquestions) < 3) { + $result->notice = get_string("notenoughsubquestions", "quiz"); + return $result; + } + break; + default: + $result->error = "Unsupported question type ($question->qtype)!"; + return $result; + } + return true; +} -// Included by import.php class qformat_default { var $displayerrors = true; var $category = NULL; var $questionids = array(); - var $qtypeconvert = array(NUMERICAL => LESSON_NUMERICAL, - MULTICHOICE => LESSON_MULTICHOICE, - TRUEFALSE => LESSON_TRUEFALSE, - SHORTANSWER => LESSON_SHORTANSWER, - MATCH => LESSON_MATCHING + var $qtypeconvert = array(NUMERICAL => LESSON_PAGE_NUMERICAL, + MULTICHOICE => LESSON_PAGE_MULTICHOICE, + TRUEFALSE => LESSON_PAGE_TRUEFALSE, + SHORTANSWER => LESSON_PAGE_SHORTANSWER, + MATCH => LESSON_PAGE_MATCHING ); -/// Importing functions + // Importing functions + function provide_import() { + return false; + } function importpreprocess() { - /// Does any pre-processing that may be desired - + // Does any pre-processing that may be desired return true; } @@ -49,6 +310,8 @@ class qformat_default { $count = 0; + $unsupportedquestions = 0; + foreach ($questions as $question) { // Process and store each question switch ($question->qtype) { // the good ones @@ -124,7 +387,7 @@ class qformat_default { $question->lessonid = $lesson->id; // needed for foreign key $question->qtype = $this->qtypeconvert[$question->qtype]; - $result = lesson_save_question_options($question); + $result = lesson_save_question_options($question, $lesson); if (!empty($result->error)) { echo $OUTPUT->notification($result->error); @@ -138,10 +401,14 @@ class qformat_default { break; // the Bad ones default : - echo $OUTPUT->notification(get_string('unsupportedqtype', 'lesson', $question->qtype)); + $unsupportedquestions++; + break; } } + if ($unsupportedquestions) { + echo $OUTPUT->notification(get_string('unknownqtypesnotimported', 'lesson', $unsupportedquestions)); + } return true; } @@ -213,7 +480,7 @@ class qformat_default { global $CFG; $question = new stdClass(); - $question->shuffleanswers = $CFG->quiz_shuffleanswers; + $question->shuffleanswers = get_config('quiz', 'shuffleanswers'); $question->defaultgrade = 1; $question->image = ""; $question->usecase = 0; @@ -232,10 +499,9 @@ class qformat_default { } function importpostprocess() { - /// Does any post-processing that may be desired - /// Argument is a simple array of question ids that - /// have just been added. - + /// Does any post-processing that may be desired + /// Argument is a simple array of question ids that + /// have just been added. return true; } diff --git a/mod/lesson/grade.php b/mod/lesson/grade.php index 52732c93bc..a100d9ccac 100644 --- a/mod/lesson/grade.php +++ b/mod/lesson/grade.php @@ -1,29 +1,47 @@ set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/grade.php', array('id'=>$id))); - - if (! $cm = get_coursemodule_from_id('lesson', $id)) { - print_error('invalidcoursemodule'); - } - - if (! $lesson = $DB->get_record("lesson", array("id" => $cm->instance))) { - print_error('invalidlessonid', 'lesson'); - } - - if (! $course = $DB->get_record("course", array("id" => $lesson->course))) { - print_error('coursemisconf'); - } - - require_login($course->id, false, $cm); - - if (has_capability('mod/lesson:edit', get_context_instance(CONTEXT_MODULE, $cm->id))) { - redirect('report.php?id='.$cm->id); - } else { - redirect('view.php?id='.$cm->id); - } - - +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Grade.php + * + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * Require config.php + */ +require_once("../../config.php"); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); + +try { + $cm = get_coursemodule_from_id('lesson', required_param('id', PARAM_INT), 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); + +$PAGE->set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/grade.php', array('id'=>$cm->id))); + +if (has_capability('mod/lesson:edit', get_context_instance(CONTEXT_MODULE, $cm->id))) { + redirect('report.php?id='.$cm->id); +} else { + redirect('view.php?id='.$cm->id); +} \ No newline at end of file diff --git a/mod/lesson/highscores.php b/mod/lesson/highscores.php index 8fc2ecbe9b..31d2976f87 100644 --- a/mod/lesson/highscores.php +++ b/mod/lesson/highscores.php @@ -1,218 +1,229 @@ . + /** * Provides the interface for viewing and adding high scores * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once('../../config.php'); - require_once('locallib.php'); - require_once('lib.php'); - - $id = required_param('id', PARAM_INT); // Course Module ID - $mode = optional_param('mode', '', PARAM_ALPHA); - $link = optional_param('link', 0, PARAM_INT); - - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/highscores.php', array('id'=>$id)); - if ($mode !== '') { - $url->param('mode', $mode); - } - if ($link !== 0) { - $url->param('link', $link); - } - $PAGE->set_url($url); - - list($cm, $course, $lesson) = lesson_get_basics($id); - - require_login($course->id, false, $cm); - - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - - switch ($mode) { - case 'add': - // Ensure that we came from view.php - if (!confirm_sesskey() or !data_submitted()) { - print_error('invalidformdata'); +/** include required files */ +require_once('../../config.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); + +$id = required_param('id', PARAM_INT); // Course Module ID +$mode = optional_param('mode', '', PARAM_ALPHA); +$link = optional_param('link', 0, PARAM_INT); + +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); + +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/highscores.php', array('id'=>$id)); +if ($mode !== '') { + $url->param('mode', $mode); +} +if ($link !== 0) { + $url->param('link', $link); +} +$PAGE->set_url($url); + +$context = get_context_instance(CONTEXT_MODULE, $cm->id); + +switch ($mode) { + case 'add': + // Ensure that we came from view.php + if (!confirm_sesskey() or !data_submitted()) { + print_error('invalidformdata'); + } + break; + + case 'save': + if (confirm_sesskey() and $form = data_submitted($CFG->wwwroot.'/mod/lesson/view.php')) { + $name = trim(optional_param('name', '', PARAM_CLEAN)); + + // Make sure it is not empty + if (empty($name)) { + $lesson->add_message(get_string('missingname', 'lesson')); + $mode = 'add'; + break; } - break; - - case 'save': - if (confirm_sesskey() and $form = data_submitted($CFG->wwwroot.'/mod/lesson/view.php')) { - $name = trim(optional_param('name', '', PARAM_CLEAN)); - - // Make sure it is not empty - if (empty($name)) { - lesson_set_message(get_string('missingname', 'lesson')); + // Check for censored words + $filterwords = explode(',', get_string('censorbadwords')); + foreach ($filterwords as $filterword) { + if (strstr($name, $filterword)) { + $lesson->add_message(get_string('namereject', 'lesson')); $mode = 'add'; break; } - // Check for censored words - $filterwords = explode(',', get_string('censorbadwords')); - foreach ($filterwords as $filterword) { - if (strstr($name, $filterword)) { - lesson_set_message(get_string('namereject', 'lesson')); - $mode = 'add'; - break; - } - } - // Bad word was found - if ($mode == 'add') { - break; - } - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if (!$grades = $DB->get_records_select('lesson_grades', "lessonid = :lessonid", $params, 'completed')) { - print_error('cannotfindfirstgrade', 'lesson'); - } + } + // Bad word was found + if ($mode == 'add') { + break; + } + $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); + if (!$grades = $DB->get_records_select('lesson_grades', "lessonid = :lessonid", $params, 'completed')) { + print_error('cannotfindfirstgrade', 'lesson'); + } - if (!$newgrade = $DB->get_record_sql("SELECT * - FROM {lesson_grades} - WHERE lessonid = :lessonid - AND userid = :userid - ORDER BY completed DESC", $params, true)) { - print_error('cannotfindnewestgrade', 'lesson'); - } + if (!$newgrade = $DB->get_record_sql("SELECT * + FROM {lesson_grades} + WHERE lessonid = :lessonid + AND userid = :userid + ORDER BY completed DESC", $params, true)) { + print_error('cannotfindnewestgrade', 'lesson'); + } - // Check for multiple submissions - if ($DB->record_exists('lesson_high_scores', array('gradeid' => $newgrade->id))) { - print_error('onpostperpage', 'lesson'); - } + // Check for multiple submissions + if ($DB->record_exists('lesson_high_scores', array('gradeid' => $newgrade->id))) { + print_error('onpostperpage', 'lesson'); + } - // Find out if we need to delete any records - if ($highscores = $DB->get_records_sql("SELECT h.*, g.grade - FROM {lesson_grades} g, {lesson_high_scores} h - WHERE h.gradeid = g.id - AND h.lessonid = :lessonid - ORDER BY g.grade DESC", $params)) { - // Only count unique scores in our total for max high scores - $uniquescores = array(); + // Find out if we need to delete any records + if ($highscores = $DB->get_records_sql("SELECT h.*, g.grade + FROM {lesson_grades} g, {lesson_high_scores} h + WHERE h.gradeid = g.id + AND h.lessonid = :lessonid + ORDER BY g.grade DESC", $params)) { + // Only count unique scores in our total for max high scores + $uniquescores = array(); + foreach ($highscores as $highscore) { + $uniquescores[$highscore->grade] = 1; + } + if (count($uniquescores) >= $lesson->maxhighscores) { + // Top scores list is full, might need to delete a score + $flag = true; + // See if the new score is already listed in the top scores list + // if it is listed, then dont need to delete any records foreach ($highscores as $highscore) { - $uniquescores[$highscore->grade] = 1; + if ($newgrade->grade == $highscore->grade) { + $flag = false; + } } - if (count($uniquescores) >= $lesson->maxhighscores) { - // Top scores list is full, might need to delete a score - $flag = true; - // See if the new score is already listed in the top scores list - // if it is listed, then dont need to delete any records + if ($flag) { + // Pushing out the lowest score (could be multiple records) + $lowscore = 0; foreach ($highscores as $highscore) { - if ($newgrade->grade == $highscore->grade) { - $flag = false; + if (empty($lowscore) or $lowscore > $highscore->grade) { + $lowscore = $highscore->grade; } } - if ($flag) { - // Pushing out the lowest score (could be multiple records) - $lowscore = 0; - foreach ($highscores as $highscore) { - if (empty($lowscore) or $lowscore > $highscore->grade) { - $lowscore = $highscore->grade; - } - } - // Now, delete all high scores with the low score - foreach ($highscores as $highscore) { - if ($highscore->grade == $lowscore) { - $DB->delete_records('lesson_high_scores', array('id' => $highscore->id)); - } + // Now, delete all high scores with the low score + foreach ($highscores as $highscore) { + if ($highscore->grade == $lowscore) { + $DB->delete_records('lesson_high_scores', array('id' => $highscore->id)); } } } } - - $newhighscore = new stdClass; - $newhighscore->lessonid = $lesson->id; - $newhighscore->userid = $USER->id; - $newhighscore->gradeid = $newgrade->id; - $newhighscore->nickname = $name; - - $DB->insert_record('lesson_high_scores', $newhighscore); - - // Log it - add_to_log($course->id, 'lesson', 'update highscores', "highscores.php?id=$cm->id", $name, $cm->id); - - lesson_set_message(get_string('postsuccess', 'lesson'), 'notifysuccess'); - redirect("$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id&link=1"); - } else { - print_error('invalidformdata'); - } - break; - } - - // Log it - add_to_log($course->id, 'lesson', 'view highscores', "highscores.php?id=$cm->id", $lesson->name, $cm->id); - - lesson_print_header($cm, $course, $lesson, 'highscores'); - - switch ($mode) { - case 'add': - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo '
-
- - - '; - - echo get_string("entername", "lesson").": \n

\n"; - lesson_print_submit_link(get_string("submitname", "lesson"), 'nickname'); - echo "

\n
\n
\n"; - echo $OUTPUT->box_end(); - break; - default: - $params = array ("lessonid" => $lesson->id); - if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid", $params, "completed")) { - $grades = array(); } - echo $OUTPUT->heading(get_string("topscorestitle", "lesson", $lesson->maxhighscores), 4); - - if (!$highscores = $DB->get_records_select("lesson_high_scores", "lessonid = :lessonid", $params)) { - echo $OUTPUT->heading(get_string("nohighscores", "lesson"), 3); - } else { - foreach ($highscores as $highscore) { - $grade = $grades[$highscore->gradeid]->grade; - $topscores[$grade][] = $highscore->nickname; + $newhighscore = new stdClass; + $newhighscore->lessonid = $lesson->id; + $newhighscore->userid = $USER->id; + $newhighscore->gradeid = $newgrade->id; + $newhighscore->nickname = $name; + + $DB->insert_record('lesson_high_scores', $newhighscore); + + // Log it + add_to_log($course->id, 'lesson', 'update highscores', "highscores.php?id=$cm->id", $name, $cm->id); + + $lesson->add_message(get_string('postsuccess', 'lesson'), 'notifysuccess'); + redirect("$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id&link=1"); + } else { + print_error('invalidformdata'); + } + break; +} + +// Log it +add_to_log($course->id, 'lesson', 'view highscores', "highscores.php?id=$cm->id", $lesson->name, $cm->id); + +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); +echo $lessonoutput->header($lesson, 'highscores'); + +switch ($mode) { + case 'add': + echo $lessonoutput->add_highscores_form($lesson); + break; + default: + $params = array ("lessonid" => $lesson->id); + if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid", $params, "completed")) { + $grades = array(); + } + + echo $OUTPUT->heading(get_string("topscorestitle", "lesson", $lesson->maxhighscores), 4); + + if (!$highscores = $DB->get_records_select("lesson_high_scores", "lessonid = :lessonid", $params)) { + echo $OUTPUT->heading(get_string("nohighscores", "lesson"), 3); + } else { + foreach ($highscores as $highscore) { + $grade = $grades[$highscore->gradeid]->grade; + $topscores[$grade][] = $highscore->nickname; + } + krsort($topscores); + + $table = new html_table(); + $table->align = array('center', 'left', 'right'); + $table->wrap = array(); + $table->width = "30%"; + $table->cellspacing = '10px'; + $table->size = array('*', '*', '*'); + + $table->head = array(get_string("rank", "lesson"), get_string('name'), get_string("scores", "lesson")); + + $printed = 0; + while (true) { + $temp = current($topscores); + $score = key($topscores); + $rank = $printed + 1; + sort($temp); + foreach ($temp as $student) { + $table->data[] = array($rank, $student, $score.'%'); } - krsort($topscores); - - $table = new html_table(); - $table->align = array('center', 'left', 'right'); - $table->wrap = array(); - $table->width = "30%"; - $table->cellspacing = '10px'; - $table->size = array('*', '*', '*'); - - $table->head = array(get_string("rank", "lesson"), get_string('name'), get_string("scores", "lesson")); - - $printed = 0; - while (true) { - $temp = current($topscores); - $score = key($topscores); - $rank = $printed + 1; - sort($temp); - foreach ($temp as $student) { - $table->data[] = array($rank, $student, $score.'%'); - } - $printed++; - if (!next($topscores) || !($printed < $lesson->maxhighscores)) { - break; - } + $printed++; + if (!next($topscores) || !($printed < $lesson->maxhighscores)) { + break; } - echo $OUTPUT->table($table); } - - if (!has_capability('mod/lesson:manage', $context)) { // teachers don't need the links - echo '"; + echo $OUTPUT->table($table); + } + + if (!has_capability('mod/lesson:manage', $context)) { // teachers don't need the links + echo $OUTPUT->box_start('mdl-align'); + echo $OUTPUT->box_start('lessonbutton standardbutton'); + if ($link) { + echo $OUTPUT->link(html_link::make(new moodle_url($CFG->wwwroot.'/course/view.php', array('id'=>$course->id)), get_string("returntocourse", "lesson"))); + } else { + echo $OUTPUT->link(html_link::make(new moodle_url($CFG->wwwroot.'/course/view.php', array('id'=>$course->id)), get_string("cancel", "lesson"))). ' '; + echo $OUTPUT->link(html_link::make(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$cm->id, 'viewed'=>'1')), get_string("startlesson", "lesson"))); } - break; - } - - echo $OUTPUT->footer(); - + echo $OUTPUT->box_end(); + echo $OUTPUT->box_end(); + } + break; +} +echo $lessonoutput->footer(); \ No newline at end of file diff --git a/mod/lesson/import.php b/mod/lesson/import.php index 48a3b503bf..3811f22563 100644 --- a/mod/lesson/import.php +++ b/mod/lesson/import.php @@ -1,128 +1,111 @@ . + /** * Imports lesson pages * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once("../../config.php"); - require_once("lib.php"); - require_once("locallib.php"); - require_once($CFG->libdir.'/questionlib.php'); - - $id = required_param('id', PARAM_INT); // Course Module ID - $pageid = optional_param('pageid', '', PARAM_INT); // Page ID +require_once("../../config.php"); +require_once($CFG->libdir.'/questionlib.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once($CFG->dirroot.'/mod/lesson/import_form.php'); +require_once($CFG->dirroot.'/mod/lesson/format.php'); // Parent class - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/import.php', array('id'=>$id)); - if ($pageid !== '') { - $url->param('pageid', $pageid); - } - $PAGE->set_url($url); +$id = required_param('id', PARAM_INT); // Course Module ID +$pageid = optional_param('pageid', '', PARAM_INT); // Page ID - if (! $cm = get_coursemodule_from_id('lesson', $id)) { - print_error('invalidcoursemodule'); - } +$PAGE->set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/import.php', array('id'=>$id, 'pageid'=>$pageid))); - if (! $course = $DB->get_record("course", array("id" => $cm->course))) { - print_error('coursemisconf'); - } +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:edit', $context); - if (! $lesson = $DB->get_record("lesson", array("id" => $cm->instance))) { - print_error('invalidcoursemodule'); - } +$strimportquestions = get_string("importquestions", "lesson"); +$strlessons = get_string("modulenameplural", "lesson"); +$manager = lesson_page_type_manager::get($lesson); - require_login($course->id, false, $cm); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - require_capability('mod/lesson:edit', $context); +$data = new stdClass; +$data->id = $PAGE->cm->id; +$data->pageid = $pageid; - $strimportquestions = get_string("importquestions", "lesson"); - $strlessons = get_string("modulenameplural", "lesson"); +$mform = new lesson_import_form(null, array('formats'=>lesson_get_import_export_formats('import'))); +$mform->set_data($data); $PAGE->navbar->add($strimportquestions); $PAGE->set_title($strimportquestions); $PAGE->set_heading($strimportquestions); echo $OUTPUT->header(); - if ($form = data_submitted()) { /// Filename +$helpicon = new moodle_help_icon(); +$helpicon->text = $strimportquestions; +$helpicon->page = "import"; +$helpicon->module = "lesson"; +echo $OUTPUT->heading_with_help($helpicon); - $form->format = clean_param($form->format, PARAM_SAFEDIR); // For safety - - if (empty($_FILES['newfile'])) { // file was just uploaded - echo $OUTPUT->notification(get_string("uploadproblem") ); - } +if ($data = $mform->get_data()) { - if ((!is_uploaded_file($_FILES['newfile']['tmp_name']) or $_FILES['newfile']['size'] == 0)) { - echo $OUTPUT->notification(get_string("uploadnofilefound") ); + require_sesskey(); - } else { // Valid file is found + if (!$importfile = $mform->get_importfile_name()) { + print_error('uploadproblem', 'moodle'); + } - if (! is_readable("$CFG->dirroot/question/format/$form->format/format.php")) { - print_error('unknowformat','', '', $form->format); + $formatclass = 'qformat_'.$data->format; + $formatclassfile = $CFG->dirroot.'/question/format/'.$data->format.'/format.php'; + if (!is_readable($formatclassfile)) { + print_error('unknowformat','', '', $data->format); } + require_once($formatclassfile); + $format = new $formatclass(); - require("format.php"); // Parent class - require("$CFG->dirroot/question/format/$form->format/format.php"); - - $classname = "qformat_$form->format"; - $format = new $classname(); - - if (! $format->importpreprocess()) { // Do anything before that we need to + // Do anything before that we need to + if (! $format->importpreprocess()) { print_error('preprocesserror', 'lesson'); } - if (! $format->importprocess($_FILES['newfile']['tmp_name'], $lesson, $pageid)) { // Process the uploaded file + // Process the uploaded file + if (! $format->importprocess($importfile, $lesson, $pageid)) { print_error('processerror', 'lesson'); } - if (! $format->importpostprocess()) { // In case anything needs to be done after + // In case anything needs to be done after + if (! $format->importpostprocess()) { print_error('postprocesserror', 'lesson'); } echo "
"; - echo $OUTPUT->continue_button("view.php?id=$cm->id"); - echo $OUTPUT->footer(); - exit; - } - } - - /// Print upload form - - $fileformatnames = get_import_export_formats('import'); - - $helpicon = new moodle_help_icon(); - $helpicon->text = $strimportquestions; - $helpicon->page = "import"; - $helpicon->module = "lesson"; - - echo $OUTPUT->heading_with_help($helpicon); - - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo "
"; - echo "id\" />\n"; - echo "\n"; - echo ""; - - echo ""; - - echo ""; - - echo "
"; - print_string("fileformat", "lesson"); - echo ":"; - echo $OUTPUT->select(html_select::make($fileformatnames, "format", "gift", false)); - echo "
"; - print_string("upload"); - echo ":"; - echo ""; - echo "
 "; - echo ""; - echo "
"; - echo "
"; - echo $OUTPUT->box_end(); + echo $OUTPUT->continue_button('view.php?id='.$PAGE->cm->id); - echo $OUTPUT->footer(); +} else { + // Print upload form + $mform->display(); +} +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/mod/lesson/import_form.php b/mod/lesson/import_form.php new file mode 100644 index 0000000000..201185ef2f --- /dev/null +++ b/mod/lesson/import_form.php @@ -0,0 +1,74 @@ +. + +/** + * Form used to select a file and file format for the import + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * Form used to select a file and file format for the import + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lesson_import_form extends moodleform { + + public function definition() { + + $mform = $this->_form; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $mform->addElement('select', 'format', get_string('fileformat', 'lesson'), $this->_customdata['formats']); + $mform->setDefault('format', 'gift'); + $mform->setType('format', 'text'); + $mform->addRule('format', null, 'required'); + + $mform->addElement('file', 'newfile', get_string('upload'), array('size'=>'50')); + $mform->addRule('newfile', null, 'required'); + + $this->add_action_buttons(null, get_string("uploadthisfile")); + + } + + public function get_importfile_name(){ + if ($this->is_submitted() and $this->is_validated()) { + // return the temporary filename to process + return $_FILES['newfile']['tmp_name']; + }else{ + return NULL; + } + } + + public function get_importfile_realname(){ + if ($this->is_submitted() and $this->is_validated()) { + // return the temporary filename to process + // TODO change this to use the files API properly. + return $_FILES['newfile']['name']; + }else{ + return NULL; + } + } + +} \ No newline at end of file diff --git a/mod/lesson/importppt.php b/mod/lesson/importppt.php index 8e7310a212..804089cb12 100644 --- a/mod/lesson/importppt.php +++ b/mod/lesson/importppt.php @@ -1,5 +1,20 @@ . + /** * This is a very rough importer for powerpoint slides * Export a powerpoint presentation with powerpoint as html pages @@ -9,293 +24,111 @@ * * The script supports book and lesson. * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once("../../config.php"); - require_once("locallib.php"); - - $id = required_param('id', PARAM_INT); // Course Module ID - $pageid = optional_param('pageid', '', PARAM_INT); // Page ID - global $matches; - - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/importppt.php', array('id'=>$id)); - if ($pageid !== '') { - $url->param('pageid', $pageid); - } - $PAGE->set_url($url); - - if (! $cm = get_coursemodule_from_id('lesson', $id)) { - print_error('invalidcoursemodule'); - } - - if (! $course = $DB->get_record("course", array("id" => $cm->course))) { - print_error('coursemisconf'); - } - - // allows for adaption for multiple modules - if(! $modname = $DB->get_field('modules', 'name', array('id' => $cm->module))) { - print_error('invalidmoduleid', '', '', $cm->module); - } - - if (! $mod = $DB->get_record($modname, array("id" => $cm->instance))) { - print_error('invalidcoursemodule'); - } - - require_login($course->id, false, $cm); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - require_capability('mod/lesson:edit', $context); - - $strimportppt = get_string("importppt", "lesson"); - $strlessons = get_string("modulenameplural", "lesson"); - - $PAGE->navbar->add($strimportppt); - $PAGE->set_title($strimportppt); - $PAGE->set_heading($strimportppt); - echo $OUTPUT->header(); - - if ($form = data_submitted()) { /// Filename - - if (empty($_FILES['newfile'])) { // file was just uploaded - echo $OUTPUT->notification(get_string("uploadproblem") ); - } - - if ((!is_uploaded_file($_FILES['newfile']['tmp_name']) or $_FILES['newfile']['size'] == 0)) { - echo $OUTPUT->notification(get_string("uploadnofilefound") ); - - } else { // Valid file is found - - if ($rawpages = readdata($_FILES, $course->id, $modname)) { // first try to reall all of the data in - $pageobjects = extract_data($rawpages, $course->id, $mod->name, $modname); // parse all the html files into objects - clean_temp(); // all done with files so dump em - - $mod_create_objects = $modname.'_create_objects'; - $mod_save_objects = $modname.'_save_objects'; - - $objects = $mod_create_objects($pageobjects, $mod->id); // function to preps the data to be sent to DB - - if(! $mod_save_objects($objects, $mod->id, $pageid)) { // sends it to DB - print_error('cannotsavedata'); - } - } else { - print_error('cannotgetdata'); - } - - echo "
"; - echo $OUTPUT->continue_button("$CFG->wwwroot/mod/$modname/view.php?id=$cm->id"); - echo $OUTPUT->footer(); - exit; - } - } - - /// Print upload form - $helpicon = new moodle_help_icon(); - $helpicon->text = $strimportppt; - $helpicon->page = "importppt"; - $helpicon->module = "lesson"; - - echo $OUTPUT->heading_with_help($helpicon); - - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo "
"; - echo "id\" />\n"; - echo "\n"; - echo ""; - - echo ""; - - echo "
"; - print_string("upload"); - echo ":"; - echo ""; - echo "
 "; - echo ""; - echo "
"; - echo "
"; - echo $OUTPUT->box_end(); - - echo $OUTPUT->footer(); - -// START OF FUNCTIONS - -function readdata($file, $courseid, $modname) { -// this function expects a zip file to be uploaded. Then it parses -// outline.htm to determine the slide path. Then parses each -// slide to get data for the content - - global $CFG; - - // create an upload directory in temp - make_upload_directory('temp/'.$modname); - - $base = $CFG->dataroot."/temp/$modname/"; +/** include required files */ +require_once("../../config.php"); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once($CFG->dirroot.'/mod/lesson/importpptlib.php'); - $zipfile = $_FILES["newfile"]["name"]; - $tempzipfile = $_FILES["newfile"]["tmp_name"]; +$id = required_param('id', PARAM_INT); // Course Module ID +$pageid = optional_param('pageid', '', PARAM_INT); // Page ID - // create our directory - $path_parts = pathinfo($zipfile); - $dirname = substr($zipfile, 0, strpos($zipfile, '.'.$path_parts['extension'])); // take off the extension - if (!file_exists($base.$dirname)) { - mkdir($base.$dirname, $CFG->directorypermissions); - } - - // move our uploaded file to temp/lesson - move_uploaded_file($tempzipfile, $base.$zipfile); - - // unzip it! - unzip_file($base.$zipfile, $base, false); - - $base = $base.$dirname; // update the base - - // this is the file where we get the names of the files for the slides (in the correct order too) - $outline = $base.'/outline.htm'; - - $pages = array(); - - if (file_exists($outline) and is_readable($outline)) { - $outlinecontents = file_get_contents($outline); - $filenames = array(); - preg_match_all("/javascript:GoToSld\('(.*)'\)/", $outlinecontents, $filenames); // this gets all of our files names - - // file $pages with the contents of all of the slides - foreach ($filenames[1] as $file) { - $path = $base.'/'.$file; - if (is_readable($path)) { - $pages[$path] = file_get_contents($path); - } else { - return false; +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/importppt.php', array('id'=>$id)); +if ($pageid !== '') { + $url->param('pageid', $pageid); +} +$PAGE->set_url($url); + +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +$modname = 'lesson'; +$mod = $cm; +require_login($course, false, $cm); + +require_login($course->id, false, $cm); +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:edit', $context); + +$strimportppt = get_string("importppt", "lesson"); +$strlessons = get_string("modulenameplural", "lesson"); + +$data = new stdClass; +$data->id = $cm->id; +$data->pageid = $pageid; +$mform = new lesson_importppt_form(); +$mform->set_data($data); + +if ($data = $mform->get_data()) { + $manager = lesson_page_type_manager::get($lesson); + if (!$filename = $mform->get_new_filename('pptzip')) { + print_error('invalidfile', 'lesson'); + } + if (!$package = $mform->save_stored_file('pptzip', $context->id, 'lesson_ppt_imports', $lesson->id, '/', $filename, true)) { + print_error('unabletosavefile', 'lesson'); + } + // extract package content + $packer = get_file_packer('application/zip'); + $package->extract_to_storage($packer, $context->id, 'lesson_imported_files', $lesson->id, '/'); + + $fs = get_file_storage(); + if ($files = $fs->get_area_files($context->id, 'lesson_imported_files', $lesson->id)) { + + $pages = array(); + foreach ($files as $key=>$file) { + if ($file->get_mimetype() != 'text/html') { + continue; } - } - } else { - // cannot find the outline, so grab all files that start with slide - $dh = opendir($base); - while (false !== ($file = readdir($dh))) { // read throug the directory - if ('slide' == substr($file, 0, 5)) { // check for name (may want to check extension later) - $path = $base.'/'.$file; - if (is_readable($path)) { - $pages[$path] = file_get_contents($path); - } else { - return false; + $filenameinfo = pathinfo($file->get_filepath().$file->get_filename()); + + $page = new stdClass; + $page->title = ''; + $page->contents = array(); + $page->images = array(); + $page->source = $filenameinfo['basename']; + + $string = strip_tags($file->get_content(),'
'); + $imgs = array(); + preg_match_all("/]*(src\=\"(".$filenameinfo['filename']."\_image[^>^\"]*)\"[^>]*)>/i", $string, $imgs); + foreach ($imgs[2] as $img) { + $imagename = basename($img); + foreach ($files as $file) { + if ($imagename === $file->get_filename()) { + $page->images[] = clone($file); + } } } - } - - ksort($pages); // order them by file name - } - - if (empty($pages)) { - return false; - } - - return $pages; -} -function extract_data($pages, $courseid, $lessonname, $modname) { - // this function attempts to extract the content out of the slides - // the slides are ugly broken xml. and the xml is broken... yeah... - - global $CFG; - global $matches; - - $extratedpages = array(); - - // directory for images - make_upload_directory($courseid.'/moddata/'.$modname, false); // we store our images in a subfolder in here - - $imagedir = $CFG->dataroot.'/'.$courseid.'/moddata/'.$modname; - - require_once($CFG->libdir .'/filelib.php'); - $imagelink = get_file_url($courseid.'/moddata/'.$modname); - - // try to make a unique subfolder to store the images - $lessonname = str_replace(' ', '_', $lessonname); // get rid of spaces - $i = 0; - while(true) { - if (!file_exists($imagedir.'/'.$lessonname.$i)) { - // ok doesnt exist so make the directory and update our paths - mkdir($imagedir.'/'.$lessonname.$i, $CFG->directorypermissions); - $imagedir = $imagedir.'/'.$lessonname.$i; - $imagelink = $imagelink.'/'.$lessonname.$i; - break; - } - $i++; - } - - foreach ($pages as $file => $content) { - // to make life easier on our preg_match_alls, we strip out all tags except - // for div and img (where our content is). We want div because sometimes we - // can identify the content in the div based on the div's class - - $tags = '
'; // should also allow - $string = strip_tags($content,$tags); - //echo s($string); - - $matches = array(); - // this will look for a non nested tag that is closed - // want to allow (maybe more) tags but when we do that - // the preg_match messes up. - preg_match_all("/(<([\w]+)[^>]*>)([^<\\2>]*)(<\/\\2>)/", $string, $matches); - //(<([\w]+)[^>]*>)([^<\\2>]*)(<\/\\2>) original pattern - //(<(div+)[^>]*>)[^() work in progress - - $path_parts = pathinfo($file); - $file = substr($path_parts['basename'], 0, strpos($path_parts['basename'], '.')); // get rid of the extension - - $imgs = array(); - // this preg matches all images - preg_match_all("/]*(src\=\"(".$file."\_image[^>^\"]*)\"[^>]*)>/i", $string, $imgs); - - // start building our page - $page = new stdClass; - $page->title = ''; - $page->contents = array(); - $page->images = array(); - $page->source = $path_parts['basename']; // need for book only - - // this foreach keeps the style intact. Found it doesn't help much. But if you want back uncomment - // this foreach and uncomment the line with the comment imgstyle in it. Also need to comment out - // the $page->images[]... line in the next foreach - /*foreach ($imgs[1] as $img) { - $page->images[] = ''; - }*/ - foreach ($imgs[2] as $img) { - copy($path_parts['dirname'].'/'.$img, $imagedir.'/'.$img); - $page->images[] = ""; // comment out this line if you are using the above foreach loop - } - for($i = 0; $i < count($matches[1]); $i++) { // go through all of our div matches - - $class = isolate_class($matches[1][$i]); // first step in isolating the class - - // check for any static classes - switch ($class) { - case 'T': // class T is used for Titles - $page->title = $matches[3][$i]; - break; - case 'B': // I would guess that all bullet lists would start with B then go to B1, B2, etc - case 'B1': // B1-B4 are just insurance, should just hit B and all be taken care of - case 'B2': - case 'B3': - case 'B4': - $page->contents[] = build_list('
    ', $i, 0); // this is a recursive function that will grab all the bullets and rebuild the list in html - break; - default: - if ($matches[3][$i] != ' ') { // odd crap generated... sigh - if (substr($matches[3][$i], 0, 1) == ':') { // check for leading : ... hate MS ... - $page->contents[] = substr($matches[3][$i], 1); // get rid of : - } else { - $page->contents[] = $matches[3][$i]; - } - } - break; - } - } - /*if (count($page->contents) == 0) { // didnt find anything, grab everything - // potential to pull in a lot of crap - for($i = 0; $i < count($matches[1]); $i++) { - //if($class = isolate_class($matches[1][$i])) { - //if ($class == 'O') { + $matches = array(); + // this will look for a non nested tag that is closed + // want to allow (maybe more) tags but when we do that + // the preg_match messes up. + preg_match_all("/(<([\w]+)[^>]*>)([^<\\2>]*)(<\/\\2>)/", $string, $matches); + for($i = 0; $i < count($matches[1]); $i++) { // go through all of our div matches + + $class = lesson_importppt_isolate_class($matches[1][$i]); // first step in isolating the class + + // check for any static classes + switch ($class) { + case 'T': // class T is used for Titles + $page->title = $matches[3][$i]; + break; + case 'B': // I would guess that all bullet lists would start with B then go to B1, B2, etc + case 'B1': // B1-B4 are just insurance, should just hit B and all be taken care of + case 'B2': + case 'B3': + case 'B4': + $page->contents[] = lesson_importppt_build_list($matches, '
      ', $i, 0); // this is a recursive function that will grab all the bullets and rebuild the list in html + break; + default: if ($matches[3][$i] != ' ') { // odd crap generated... sigh if (substr($matches[3][$i], 0, 1) == ':') { // check for leading : ... hate MS ... $page->contents[] = substr($matches[3][$i], 1); // get rid of : @@ -303,292 +136,82 @@ function extract_data($pages, $courseid, $lessonname, $modname) { $page->contents[] = $matches[3][$i]; } } - //} - //} - } - }*/ - // add the page to the array; - $extratedpages[] = $page; - - } // end $pages foreach loop - - return $extratedpages; -} - -/** -A recursive function to build a html list -*/ -function build_list($list, &$i, $depth) { - global $matches; // not sure why I global this... - - while($i < count($matches[1])) { - - $class = isolate_class($matches[1][$i]); - - if (strstr($class, 'B')) { // make sure we are still working with bullet classes - if ($class == 'B') { - $this_depth = 0; // calling class B depth 0 - } else { - // set the depth number. So B1 is depth 1 and B2 is depth 2 and so on - $this_depth = substr($class, 1); - if (!is_numeric($this_depth)) { - print_error('invalidnum'); + break; } } - if ($this_depth < $depth) { - // we are moving back a level in the nesting - break; - } - if ($this_depth > $depth) { - // we are moving in a lvl in nesting - $list .= '
        '; - $list = build_list($list, $i, $this_depth); - // once we return back, should go to the start of the while - continue; - } - // no depth changes, so add the match to our list - if ($cleanstring = ppt_clean_text($matches[3][$i])) { - $list .= '
      • '.ppt_clean_text($matches[3][$i]).'
      • '; - } - $i++; - } else { - // not a B class, so get out of here... - break; + $pages[] = $page; } - } - // end the list and return it - $list .= '
      '; - return $list; -} + $branchtables = lesson_create_objects($pages, $lesson->id); -/** -Given an html tag, this function will -*/ -function isolate_class($string) { - if($class = strstr($string, 'class=')) { // first step in isolating the class - $class = substr($class, strpos($class, '=')+1); // this gets rid of
      get_field('lesson_pages', 'id', array('prevpageid' => 0, 'lessonid' => $lesson->id))) { + $nextpageid = 0; + } } else { - // no spaces so nothing else in the div tag, cut off the > - return substr($class, 0, strpos($class, '>')); + // going after an actual page + $prevpageid = $pageid; + $nextpageid = $DB->get_field('lesson_pages', 'nextpageid', array('id' => $pageid)); } - } else { - // no class defined in the tag - return ''; - } -} - -/** -This function strips off the random chars that ppt puts infront of bullet lists -*/ -function ppt_clean_text($string) { - $chop = 1; // default: just a single char infront of the content - - // look for any other crazy things that may be infront of the content - if (strstr($string, '<') and strpos($string, '<') == 0) { // look for the < in the sting and make sure it is in the front - $chop = 4; // increase the $chop - } - // may need to add more later.... - - $string = substr($string, $chop); - - if ($string != ' ') { - return $string; - } else { - return false; - } -} - -/** - Clean up the temp directory -*/ -function clean_temp() { - global $CFG; - // this function is broken, use it to clean up later - // should only clean up what we made as well because someone else could be importing ppt as well - //delDirContents($CFG->dataroot.'/temp/lesson'); -} - -/** - Creates objects an object with the page and answers that are to be inserted into the database -*/ -function lesson_create_objects($pageobjects, $lessonid) { - - $branchtables = array(); - $branchtable = new stdClass; - - // all pages have this info - $page->lessonid = $lessonid; - $page->prevpageid = 0; - $page->nextpageid = 0; - $page->qtype = LESSON_BRANCHTABLE; - $page->qoption = 0; - $page->layout = 1; - $page->display = 1; - $page->timecreated = time(); - $page->timemodified = 0; - - // all answers are the same - $answer->lessonid = $lessonid; - $answer->jumpto = LESSON_NEXTPAGE; - $answer->grade = 0; - $answer->score = 0; - $answer->flags = 0; - $answer->timecreated = time(); - $answer->timemodified = 0; - $answer->answer = "Next"; - $answer->response = ""; - - $answers[] = clone($answer); - - $answer->jumpto = LESSON_PREVIOUSPAGE; - $answer->answer = "Previous"; - $answers[] = clone($answer); + foreach ($branchtables as $branchtable) { - $branchtable->answers = $answers; + // set the doubly linked list + $branchtable->page->nextpageid = $nextpageid; + $branchtable->page->prevpageid = $prevpageid; - $i = 1; + // insert the page + $id = $DB->insert_record('lesson_pages', $branchtable->page); - foreach ($pageobjects as $pageobject) { - $temp = prep_page($pageobject, $i); // makes our title and contents - $page->title = $temp->title; - $page->contents = $temp->contents; - $branchtable->page = clone($page); // add the page - $branchtables[] = clone($branchtable); // add it all to our array - $i++; - } - - return $branchtables; -} - -/** - Creates objects an chapter object that is to be inserted into the database -*/ -function book_create_objects($pageobjects, $bookid) { - global $DB; - - $chapters = array(); - $chapter = new stdClass; - - // same for all chapters - $chapter->bookid = $bookid; - $chapter->pagenum = $DB->count_records('book_chapters', array('bookid'=>$bookid))+1; - $chapter->timecreated = time(); - $chapter->timemodified = time(); - $chapter->subchapter = 0; - - $i = 1; - foreach ($pageobjects as $pageobject) { - $page = prep_page($pageobject, $i); // get title and contents - $chapter->importsrc = $pageobject->source; // add the source - $chapter->title = $page->title; - $chapter->content = $page->contents; - $chapters[] = $chapter; - - // increment our page number and our counter - $chapter->pagenum = $chapter->pagenum + 1; - $i++; - } - - return $chapters; -} - -/** - Builds the title and content strings from an object -*/ -function prep_page($pageobject, $count) { - if ($pageobject->title == '') { - $page->title = "Page $count"; // no title set so make a generic one - } else { - $page->title = $pageobject->title; - } - - $page->contents = ''; - - // nab all the images first - foreach ($pageobject->images as $image) { - $image = str_replace("\n", '', $image); - $image = str_replace("\r", '', $image); - $image = str_replace("'", '"', $image); // imgstyle - - $page->contents .= $image; - } - // go through the contents array and put

      tags around each element and strip out \n which I have found to be uneccessary - foreach ($pageobject->contents as $content) { - $content = str_replace("\n", '', $content); - $content = str_replace("\r", '', $content); - $content = str_replace(' ', '', $content); // puts in returns? - $content = '

      '.$content.'

      '; - $page->contents .= $content; - } - return $page; -} - -/** - Saves the branchtable objects to the DB -*/ -function lesson_save_objects($branchtables, $lessonid, $after) { - global $DB; - - // first set up the prevpageid and nextpageid - if ($after == 0) { // adding it to the top of the lesson - $prevpageid = 0; - // get the id of the first page. If not found, then no pages in the lesson - if (!$nextpageid = $DB->get_field('lesson_pages', 'id', array('prevpageid' => 0, 'lessonid' => $lessonid))) { - $nextpageid = 0; - } - } else { - // going after an actual page - $prevpageid = $after; - $nextpageid = $DB->get_field('lesson_pages', 'nextpageid', array('id' => $after)); - } - - foreach ($branchtables as $branchtable) { + if (!empty($branchtable->page->images)) { + $changes = array('contextid'=>$context->id, 'filearea'=>'lesson_page_contents', 'itemid'=>$id, 'timemodified'=>time()); + foreach ($branchtable->page->images as $image) { + $fs->create_file_from_storedfile($changes, $image); + } + } - // set the doubly linked list - $branchtable->page->nextpageid = $nextpageid; - $branchtable->page->prevpageid = $prevpageid; + // update the link of the page previous to the one we just updated + if ($prevpageid != 0) { // if not the first page + $DB->set_field("lesson_pages", "nextpageid", $id, array("id" => $prevpageid)); + } - // insert the page - $id = $DB->insert_record('lesson_pages', $branchtable->page); + // insert the answers + foreach ($branchtable->answers as $answer) { + $answer->pageid = $id; + $DB->insert_record('lesson_answers', $answer); + } - // update the link of the page previous to the one we just updated - if ($prevpageid != 0) { // if not the first page - $DB->set_field("lesson_pages", "nextpageid", $id, array("id" => $prevpageid)); + $prevpageid = $id; } - // insert the answers - foreach ($branchtable->answers as $answer) { - $answer->pageid = $id; - $DB->insert_record('lesson_answers', $answer); + // all done with inserts. Now check to update our last page (this is when we import between two lesson pages) + if ($nextpageid != 0) { // if the next page is not the end of lesson + $DB->set_field("lesson_pages", "prevpageid", $id, array("id" => $nextpageid)); } - - $prevpageid = $id; } - // all done with inserts. Now check to update our last page (this is when we import between two lesson pages) - if ($nextpageid != 0) { // if the next page is not the end of lesson - $DB->set_field("lesson_pages", "prevpageid", $id, array("id" => $nextpageid)); - } + // Remove all unzipped files! + $fs->delete_area_files($context->id, 'lesson_imported_files', $lesson->id); - return true; + redirect("$CFG->wwwroot/mod/$modname/view.php?id=$cm->id", get_string('pptsuccessfullimport', 'lesson'), 5); } -/** - Save the chapter objects to the database -*/ -function book_save_objects($chapters, $bookid, $pageid='0') { - global $DB; - - // nothing fancy, just save them all in order - foreach ($chapters as $chapter) { - $chapter->id = $DB->insert_record('book_chapters', $chapter); - } - return true; -} - - +$PAGE->navbar->add($strimportppt); +$PAGE->set_title($strimportppt); +$PAGE->set_heading($strimportppt); +echo $OUTPUT->header(); + +/// Print upload form +$helpicon = new moodle_help_icon(); +$helpicon->text = $strimportppt; +$helpicon->page = "importppt"; +$helpicon->module = "lesson"; + +echo $OUTPUT->heading_with_help($helpicon); +echo $OUTPUT->box_start('generalbox boxaligncenter'); +$mform->display(); +echo $OUTPUT->box_end(); +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/mod/lesson/importpptlib.php b/mod/lesson/importpptlib.php new file mode 100644 index 0000000000..2161dae69a --- /dev/null +++ b/mod/lesson/importpptlib.php @@ -0,0 +1,231 @@ +. + +/** + * Contains functions used by importppt.php that naturally pertain to importing + * powerpoint presentations into the lesson module + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * A recursive function to build a html list + * + * @param array $matches + * @param string $list + * @param int $i + * @param int $depth + * @return string + */ +function lesson_importppt_build_list(array &$matches, $list, &$i, $depth) { + while($i < count($matches[1])) { + + $class = lesson_importppt_isolate_class($matches[1][$i]); + + if (strstr($class, 'B')) { // make sure we are still working with bullet classes + if ($class == 'B') { + $this_depth = 0; // calling class B depth 0 + } else { + // set the depth number. So B1 is depth 1 and B2 is depth 2 and so on + $this_depth = substr($class, 1); + if (!is_numeric($this_depth)) { + print_error('invalidnum'); + } + } + if ($this_depth < $depth) { + // we are moving back a level in the nesting + break; + } + if ($this_depth > $depth) { + // we are moving in a lvl in nesting + $list .= '
        '; + $list = lesson_importppt_build_list($matches, $list, $i, $this_depth); + // once we return back, should go to the start of the while + continue; + } + // no depth changes, so add the match to our list + if ($cleanstring = lesson_importppt_clean_text($matches[3][$i])) { + $list .= '
      • '.lesson_importppt_clean_text($matches[3][$i]).'
      • '; + } + $i++; + } else { + // not a B class, so get out of here... + break; + } + } + // end the list and return it + $list .= '
      '; + return $list; + +} + +/** + * Given an html tag, this function will + * + * @param string $string + * @return string + */ +function lesson_importppt_isolate_class($string) { + if($class = strstr($string, 'class=')) { // first step in isolating the class + $class = substr($class, strpos($class, '=')+1); // this gets rid of
      + return substr($class, 0, strpos($class, '>')); + } + } else { + // no class defined in the tag + return ''; + } +} + +/** + * This function strips off the random chars that ppt puts infront of bullet lists + * + * @param string $string + * @return string + */ +function lesson_importppt_clean_text($string) { + $chop = 1; // default: just a single char infront of the content + + // look for any other crazy things that may be infront of the content + if (strstr($string, '<') and strpos($string, '<') == 0) { // look for the < in the sting and make sure it is in the front + $chop = 4; // increase the $chop + } + // may need to add more later.... + + $string = substr($string, $chop); + + if ($string != ' ') { + return $string; + } else { + return false; + } +} + +/** + * Creates objects an object with the page and answers that are to be inserted into the database + * + * @param array $pageobjects + * @param int $lessonid + * @return array + */ +function lesson_create_objects($pageobjects, $lessonid) { + + $branchtables = array(); + $branchtable = new stdClass; + + // all pages have this info + $page->lessonid = $lessonid; + $page->prevpageid = 0; + $page->nextpageid = 0; + $page->qtype = LESSON_PAGE_BRANCHTABLE; + $page->qoption = 0; + $page->layout = 1; + $page->display = 1; + $page->timecreated = time(); + $page->timemodified = 0; + + // all answers are the same + $answer->lessonid = $lessonid; + $answer->jumpto = LESSON_NEXTPAGE; + $answer->grade = 0; + $answer->score = 0; + $answer->flags = 0; + $answer->timecreated = time(); + $answer->timemodified = 0; + $answer->answer = "Next"; + $answer->response = ""; + + $answers[] = clone($answer); + + $answer->jumpto = LESSON_PREVIOUSPAGE; + $answer->answer = "Previous"; + + $answers[] = clone($answer); + + $branchtable->answers = $answers; + + $i = 1; + + foreach ($pageobjects as $pageobject) { + if ($pageobject->title == '') { + $page->title = "Page $i"; // no title set so make a generic one + } else { + $page->title = $pageobject->title; + } + $page->contents = ''; + + // nab all the images first + $page->images = $pageobject->images; + foreach ($page->images as $image) { + $imagetag = ''; + $imagetag = str_replace("\n", '', $imagetag); + $imagetag = str_replace("\r", '', $imagetag); + $imagetag = str_replace("'", '"', $imagetag); // imgstyle + $page->contents .= $imagetag; + } + // go through the contents array and put

      tags around each element and strip out \n which I have found to be uneccessary + foreach ($pageobject->contents as $content) { + $content = str_replace("\n", '', $content); + $content = str_replace("\r", '', $content); + $content = str_replace(' ', '', $content); // puts in returns? + $content = '

      '.$content.'

      '; + $page->contents .= $content; + } + + $branchtable->page = clone($page); // add the page + $branchtables[] = clone($branchtable); // add it all to our array + $i++; + } + + return $branchtables; +} + +/** + * Form displayed to the user asking them to select a file to upload + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lesson_importppt_form extends moodleform { + + public function definition() { + global $COURSE; + + $mform = $this->_form; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $filepickeroptions = array(); + $filepickeroptions['filetypes'] = array('*.zip'); + $filepickeroptions['maxbytes'] = $COURSE->maxbytes; + $mform->addElement('filepicker', 'pptzip', get_string('upload'), null, $filepickeroptions); + $mform->addRule('pptzip', null, 'required', null, 'client'); + + $this->add_action_buttons(null, get_string("uploadthisfile")); + } + +} \ No newline at end of file diff --git a/mod/lesson/index.php b/mod/lesson/index.php index d803c3b73f..86ac45f844 100644 --- a/mod/lesson/index.php +++ b/mod/lesson/index.php @@ -1,111 +1,119 @@ . + /** * This page lists all the instances of lesson in a particular course * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once("../../config.php"); - require_once($CFG->dirroot.'/mod/lesson/lib.php'); - require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +/** Include required files */ +require_once("../../config.php"); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); - $id = required_param('id', PARAM_INT); // course +$id = required_param('id', PARAM_INT); // course - $PAGE->set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/index.php', array('id'=>$id))); +$PAGE->set_url(new moodle_url($CFG->wwwroot.'/mod/lesson/index.php', array('id'=>$id))); - if (!$course = $DB->get_record("course", array("id" => $id))) { - print_error('invalidcourseid'); - } +if (!$course = $DB->get_record("course", array("id" => $id))) { + print_error('invalidcourseid'); +} - require_login($course->id); +require_login($course); - add_to_log($course->id, "lesson", "view all", "index.php?id=$course->id", ""); +add_to_log($course->id, "lesson", "view all", "index.php?id=$course->id", ""); /// Get all required strings - $strlessons = get_string("modulenameplural", "lesson"); - $strlesson = get_string("modulename", "lesson"); +$strlessons = get_string("modulenameplural", "lesson"); +$strlesson = get_string("modulename", "lesson"); /// Print the header - $PAGE->navbar->add($strlessons); - $PAGE->set_title("$course->shortname: $strlessons"); - $PAGE->set_heading($course->fullname); - echo $OUTPUT->header(); +$PAGE->navbar->add($strlessons); +$PAGE->set_title("$course->shortname: $strlessons"); +$PAGE->set_heading($course->fullname); +echo $OUTPUT->header(); /// Get all the appropriate data - if (! $lessons = get_all_instances_in_course("lesson", $course)) { - notice(get_string('thereareno', 'moodle', $strlessons), "../../course/view.php?id=$course->id"); - die; - } +if (! $lessons = get_all_instances_in_course("lesson", $course)) { + notice(get_string('thereareno', 'moodle', $strlessons), "../../course/view.php?id=$course->id"); + die; +} /// Print the list of instances (your module will probably extend this) - $timenow = time(); - $strname = get_string("name"); - $strgrade = get_string("grade"); - $strdeadline = get_string("deadline", "lesson"); - $strweek = get_string("week"); - $strtopic = get_string("topic"); - $strnodeadline = get_string("nodeadline", "lesson"); - $table = new html_table(); - - if ($course->format == "weeks") { - $table->head = array ($strweek, $strname, $strgrade, $strdeadline); - $table->align = array ("center", "left", "center", "center"); - } else if ($course->format == "topics") { - $table->head = array ($strtopic, $strname, $strgrade, $strdeadline); - $table->align = array ("center", "left", "center", "center"); +$timenow = time(); +$strname = get_string("name"); +$strgrade = get_string("grade"); +$strdeadline = get_string("deadline", "lesson"); +$strweek = get_string("week"); +$strtopic = get_string("topic"); +$strnodeadline = get_string("nodeadline", "lesson"); +$table = new html_table(); + +if ($course->format == "weeks") { + $table->head = array ($strweek, $strname, $strgrade, $strdeadline); + $table->align = array ("center", "left", "center", "center"); +} else if ($course->format == "topics") { + $table->head = array ($strtopic, $strname, $strgrade, $strdeadline); + $table->align = array ("center", "left", "center", "center"); +} else { + $table->head = array ($strname, $strgrade, $strdeadline); + $table->align = array ("left", "center", "center"); +} + +foreach ($lessons as $lesson) { + if (!$lesson->visible) { + //Show dimmed if the mod is hidden + $link = "coursemodule\">".format_string($lesson->name,true).""; } else { - $table->head = array ($strname, $strgrade, $strdeadline); - $table->align = array ("left", "center", "center"); + //Show normal if the mod is visible + $link = "coursemodule\">".format_string($lesson->name,true).""; } + $cm = get_coursemodule_from_instance('lesson', $lesson->id); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); - foreach ($lessons as $lesson) { - if (!$lesson->visible) { - //Show dimmed if the mod is hidden - $link = "coursemodule\">".format_string($lesson->name,true).""; - } else { - //Show normal if the mod is visible - $link = "coursemodule\">".format_string($lesson->name,true).""; - } - $cm = get_coursemodule_from_instance('lesson', $lesson->id); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); + if ($lesson->deadline == 0) { + $due = $strnodeadline; + } else if ($lesson->deadline > $timenow) { + $due = userdate($lesson->deadline); + } else { + $due = "".userdate($lesson->deadline).""; + } - if ($lesson->deadline == 0) { - $due = $strnodeadline; - } else if ($lesson->deadline > $timenow) { - $due = userdate($lesson->deadline); + if ($course->format == "weeks" or $course->format == "topics") { + if (has_capability('mod/lesson:manage', $context)) { + $grade_value = $lesson->grade; } else { - $due = "".userdate($lesson->deadline).""; - } - - if ($course->format == "weeks" or $course->format == "topics") { - if (has_capability('mod/lesson:manage', $context)) { - $grade_value = $lesson->grade; - } else { - // it's a student, show their grade - $grade_value = 0; - if ($return = lesson_get_user_grades($lesson, $USER->id)) { - $grade_value = $return[$USER->id]->rawgrade; - } + // it's a student, show their grade + $grade_value = 0; + if ($return = lesson_get_user_grades($lesson, $USER->id)) { + $grade_value = $return[$USER->id]->rawgrade; } - $table->data[] = array ($lesson->section, $link, $grade_value, $due); - } else { - $table->data[] = array ($link, $lesson->grade, $due); } + $table->data[] = array ($lesson->section, $link, $grade_value, $due); + } else { + $table->data[] = array ($link, $lesson->grade, $due); } - - echo "
      "; - - echo $OUTPUT->table($table); - -/// Finish the page - - echo $OUTPUT->footer(); - - +} +echo $OUTPUT->table($table); +echo $OUTPUT->footer(); \ No newline at end of file diff --git a/mod/lesson/styles.php b/mod/lesson/lesson.css similarity index 88% rename from mod/lesson/styles.php rename to mod/lesson/lesson.css index d175799066..d2739a27e5 100644 --- a/mod/lesson/styles.php +++ b/mod/lesson/lesson.css @@ -6,6 +6,18 @@ text-align: left; } +.mod-lesson .standardtable, +.mod-lesson .mform .box.contents { + text-align: left; + margin:1em auto; + width:80%; +} + +.mod-lesson .compacttable { + margin:0px auto; + width:80%; +} + .mod-lesson #layout-table { width: 100%; } @@ -21,6 +33,7 @@ .mod-lesson .addlinks { font-size: .8em; + margin:5px auto; } .mod-lesson .userinfotable .cell, @@ -146,6 +159,10 @@ width: 20em; } +.mod-lesson .edit_pages_box { + width:80%; + margin-left:10%; +} /*** *** Lesson Buttons @@ -206,22 +223,12 @@ } .mod-lesson .progress_bar_completed { - /* Example Use of Image - background-image: url(wwwroot ?>/mod/lesson/completed.gif); - background-position: center; - background-repeat: repeat-x; - */ background-color: green; padding: 0px; margin: 0px; } .mod-lesson .progress_bar_todo { - /* Example Use of Image - background-image: url(wwwroot ?>/mod/lesson/todo.gif); - background-repeat: repeat-x; - background-position: center; - */ background-color: red; text-align: left; padding: 0px; @@ -229,13 +236,25 @@ } .mod-lesson .progress_bar_token { - /* Example Use of Image - background-image: url(wwwroot ?>/mod/lesson/token.gif); - background-repeat: repeat-none; - */ background-color: #000000; height: 20px; width: 5px; padding: 0px; margin: 0px; } + +.mod-lesson .center { + text-align:center; +} + +.mod-lesson .centerpadded { + text-align:center; + padding:5px; +} + +.mod-lesson .firstpageoptions { + width:30%; + margin-left:35%; + margin-top:1em; + text-align:center; +} \ No newline at end of file diff --git a/mod/lesson/lesson.php b/mod/lesson/lesson.php index 78ecdbc55d..bab8733877 100644 --- a/mod/lesson/lesson.php +++ b/mod/lesson/lesson.php @@ -1,67 +1,171 @@ . + /** * Handles lesson actions * * ACTIONS handled are: - * addbranchtable - * addendofbranch - * addcluster - * addendofcluster - * addpage * confirmdelete - * continue * delete - * editpage - * insertpage * move * moveit - * updatepage - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require("../../config.php"); - require("locallib.php"); +require_once("../../config.php"); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); - $id = required_param('id', PARAM_INT); // Course Module ID - $action = required_param('action', PARAM_ALPHA); // Action +$id = required_param('id', PARAM_INT); // Course Module ID +$action = required_param('action', PARAM_ALPHA); // Action +$pageid = required_param('pageid', PARAM_INT); - list($cm, $course, $lesson) = lesson_get_basics($id); +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); - require_login($course, false, $cm); +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/lesson.php', array('id'=>$id,'action'=>$action)); +$PAGE->set_url($url); +$PAGE->navbar->add(get_string($action, 'lesson')); - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/edit.php', array('id'=>$id,'action'=>$action)); - $PAGE->set_url($url); - $PAGE->navbar->add(get_string($action, 'lesson')); +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:edit', $context); +require_sesskey(); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - -/// Set up some general variables - $usehtmleditor = can_use_html_editor(); +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); /// Process the action - switch ($action) { - case 'addbranchtable': - case 'addpage': - case 'confirmdelete': - case 'editpage': - case 'move': - lesson_print_header($cm, $course, $lesson); - case 'addcluster': - case 'addendofbranch': - case 'addendofcluster': - case 'delete': - case 'insertpage': - case 'updatepage': - case 'moveit': - require_capability('mod/lesson:edit', $context); - case 'continue': - include($CFG->dirroot.'/mod/lesson/action/'.$action.'.php'); - break; - default: - print_error('unknowaction'); - } - - echo $OUTPUT->footer(); +switch ($action) { + case 'confirmdelete': + $thispage = $lesson->load_page($pageid); + + echo $lessonoutput->header($lesson); + echo $OUTPUT->heading(get_string("deletingpage", "lesson", format_string($thispage->title))); + // print the jumps to this page + $params = array("lessonid" => $lesson->id, "pageid" => $pageid); + if ($answers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid AND jumpto = :pageid + 1", $params)) { + echo $OUTPUT->heading(get_string("thefollowingpagesjumptothispage", "lesson")); + echo "

      \n"; + foreach ($answers as $answer) { + if (!$title = $DB->get_field("lesson_pages", "title", array("id" => $answer->pageid))) { + print_error('cannotfindpagetitle', 'lesson'); + } + echo $title."
      \n"; + } + } + echo $OUTPUT->confirm(get_string("confirmdeletionofthispage","lesson"),"lesson.php?action=delete&id=$cm->id&pageid=$pageid","view.php?id=$cm->id"); + + break; + case 'move': + + $title = $DB->get_field("lesson_pages", "title", array("id" => $pageid)); + + echo $lessonoutput->header($lesson); + echo $OUTPUT->heading(get_string("moving", "lesson", format_string($title))); + + $params = array ("lessonid" => $lesson->id, "prevpageid" => 0); + if (!$page = $DB->get_record_select("lesson_pages", "lessonid = :lessonid AND prevpageid = :prevpageid", $params)) { + print_error('cannotfindfirstpage', 'lesson'); + } + + echo "

      \n"; + echo "\n"; + while (true) { + if ($page->id != $pageid) { + if (!$title = trim(format_string($page->title))) { + $title = "<< ".get_string("notitle", "lesson")." >>"; + } + echo "\n"; + echo "\n"; + } + if ($page->nextpageid) { + if (!$page = $DB->get_record("lesson_pages", array("id" => $page->nextpageid))) { + print_error('cannotfindnextpage', 'lesson'); + } + } else { + // last page reached + break; + } + } + echo "
      id&sesskey=".sesskey()."&action=moveit&pageid=$pageid&after=0\">". + get_string("movepagehere", "lesson")."
      $title
      id&sesskey=".sesskey()."&action=moveit&pageid=$pageid&after={$page->id}\">". + get_string("movepagehere", "lesson")."
      \n"; + + break; + case 'delete': + $thispage = $lesson->load_page($pageid); + $thispage->delete(); + $lesson->add_message(get_string('deletedpage', 'lesson').': '.format_string($thispage->title, true), 'notifysuccess'); + redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); + break; + case 'moveit': + $after = (int)required_param('after', PARAM_INT); // target page + + $pages = $lesson->load_all_pages(); + + if (!array_key_exists($pageid, $pages) || ($after!=0 && !array_key_exists($after, $pages))) { + print_error('Unable to find the page to move'); + } + $pagetomove = clone($pages[$pageid]); + unset($pages[$pageid]); + + $pageids = array(); + if ($after === 0) { + $pageids['p0'] = $pageid; + } + foreach ($pages as $page) { + $pageids[] = $page->id; + if ($page->id == $after) { + $pageids[] = $pageid; + } + } + + $pageidsref = $pageids; + reset($pageidsref); + $prev = 0; + $next = next($pageidsref); + foreach ($pageids as $pid) { + if ($pid === $pageid) { + $page = $pagetomove; + } else { + $page = $pages[$pid]; + } + if ($page->prevpageid != $prev || $page->nextpageid != $next) { + $page->move($next, $prev); + } + $prev = $page->id; + $next = next($pageidsref); + if (!$next) { + $next = 0; + } + } + $lesson->add_message(get_string('movedpage', 'lesson'), 'notifysuccess'); + redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); + break; + default: + print_error('unknowaction'); + break; +} +echo $lessonoutput->footer(); \ No newline at end of file diff --git a/mod/lesson/lib.php b/mod/lesson/lib.php index 3d181f3e84..29320d6d45 100644 --- a/mod/lesson/lib.php +++ b/mod/lesson/lib.php @@ -18,13 +18,16 @@ /** * Standard library of functions and constants for lesson * - * @package mod-lesson + * @package lesson * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ -/** Include {@link eventslib.php} */ +/** Include required libraries */ require_once($CFG->libdir.'/eventslib.php'); +require_once($CFG->libdir.'/filelib.php'); +require_once($CFG->dirroot.'/calendar/lib.php'); +require_once($CFG->dirroot.'/course/moodleform_mod.php'); /** LESSON_MAX_EVENT_LENGTH = 432000 ; 5 days maximum */ define("LESSON_MAX_EVENT_LENGTH", "432000"); @@ -40,16 +43,29 @@ define("LESSON_MAX_EVENT_LENGTH", "432000"); * @param object $lesson Lesson post data from the form * @return int **/ -function lesson_add_instance($lesson) { +function lesson_add_instance($data, $mform) { global $SESSION, $DB; - lesson_process_pre_save($lesson); + $cmid = $data->coursemodule; - $lesson->id = $DB->insert_record("lesson", $lesson); + lesson_process_pre_save($data); - lesson_process_post_save($lesson); + unset($data->mediafile); + $lessonid = $DB->insert_record("lesson", $data); + $data->id = $lessonid; - lesson_grade_item_update($lesson); + $context = get_context_instance(CONTEXT_MODULE, $cmid); + $lesson = $DB->get_record('lesson', array('id'=>$lessonid), '*', MUST_EXIST); + + if ($filename = $mform->get_new_filename('mediafile')) { + if ($file = $mform->save_stored_file('mediafile', $context->id, 'lesson_media_file', $lesson->id, '/', $filename)) { + $DB->set_field('lesson', 'mediafile', $file->get_filename(), array('id'=>$lesson->id)); + } + } + + lesson_process_post_save($data); + + lesson_grade_item_update($data); return $lesson->id; } @@ -63,24 +79,33 @@ function lesson_add_instance($lesson) { * @param object $lesson Lesson post data from the form * @return boolean **/ -function lesson_update_instance($lesson) { +function lesson_update_instance($data, $mform) { global $DB; - $lesson->id = $lesson->instance; + $data->id = $data->instance; + $cmid = $data->coursemodule; - lesson_process_pre_save($lesson); + lesson_process_pre_save($data); - if (!$result = $DB->update_record("lesson", $lesson)) { + unset($data->mediafile); + if (!$result = $DB->update_record("lesson", $data)) { return false; // Awe man! } - lesson_process_post_save($lesson); + $context = get_context_instance(CONTEXT_MODULE, $cmid); + if ($filename = $mform->get_new_filename('mediafile')) { + if ($file = $mform->save_stored_file('mediafile', $context->id, 'lesson_media_file', $data->id, '/', $filename, true)) { + $DB->set_field('lesson', 'mediafile', $file->get_filename(), array('id'=>$data->id)); + } + } + + lesson_process_post_save($data); // update grade item definition - lesson_grade_item_update($lesson); + lesson_grade_item_update($data); // update grades - TODO: do it only when grading style changes - lesson_update_grades($lesson, 0, false); + lesson_update_grades($data, 0, false); return $result; } @@ -97,53 +122,14 @@ function lesson_update_instance($lesson) { */ function lesson_delete_instance($id) { global $DB; - - if (! $lesson = $DB->get_record("lesson", array("id"=>$id))) { - return false; - } - - $result = true; - - if (! $DB->delete_records("lesson", array("id"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_pages", array("lessonid"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_answers", array("lessonid"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_attempts", array("lessonid"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_grades", array("lessonid"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_timer", array("lessonid"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_branch", array("lessonid"=>$lesson->id))) { - $result = false; - } - if (! $DB->delete_records("lesson_high_scores", array("lessonid"=>$lesson->id))) { - $result = false; - } - if ($events = $DB->get_records('event', array("modulename"=>'lesson', "instance"=>$lesson->id))) { - foreach($events as $event) { - delete_event($event->id); - } - } - - lesson_grade_item_delete($lesson); - - return $result; + $lesson = $DB->get_record("lesson", array("id"=>$id), '*', MUST_EXIST); + $lesson = new lesson($lesson); + return $lesson->delete(); } /** * Given a course object, this function will clean up anything that - * would be leftover after all the instances were deleted. - * - * As of now, this function just cleans the lesson_default table + * would be leftover after all the instances were deleted * * @global object * @param object $course an object representing the course that is being deleted @@ -151,16 +137,6 @@ function lesson_delete_instance($id) { * @return boolean */ function lesson_delete_course($course, $feedback=true) { - global $DB, $OUTPUT; - - $count = $DB->count_records('lesson_default', array('course'=>$course->id)); - $DB->delete_records('lesson_default', array('course' => $course->id)); - - //Inform about changes performed if feedback is enabled - if ($feedback) { - echo $OUTPUT->notification(get_string('deletedefaults', 'lesson', $count)); - } - return true; } @@ -527,9 +503,7 @@ function lesson_grade_item_update($lesson, $grades=NULL) { */ function lesson_grade_item_delete($lesson) { global $CFG; - require_once($CFG->libdir.'/gradelib.php'); - - return grade_update('mod/lesson', $lesson->course, 'mod', 'lesson', $lesson->id, 0, NULL, array('deleted'=>1)); + } @@ -569,7 +543,7 @@ function lesson_get_view_actions() { * @return array */ function lesson_get_post_actions() { - return array('end','start', 'update grade attempt'); + return array('end','start'); } /** @@ -600,6 +574,16 @@ function lesson_process_pre_save(&$lesson) { $lesson->gradebetterthan = 100; } + if (empty($lesson->width)) { + $lesson->width = 640; + } + if (empty($lesson->height)) { + $lesson->height = 480; + } + if (empty($lesson->bgcolor)) { + $lesson->bgcolor = '#FFFFFF'; + } + // Conditions for dependency $conditions = new stdClass; $conditions->timespent = $lesson->timespent; @@ -613,21 +597,6 @@ function lesson_process_pre_save(&$lesson) { if (empty($lesson->password)) { unset($lesson->password); } - - if ($lesson->lessondefault) { - $default = new stdClass; - $default = clone($lesson); - unset($default->name); - unset($default->timemodified); - unset($default->available); - unset($default->deadline); - if ($default->id = $DB->get_field('lesson_default', 'id', array('course' => $default->course))) { - $DB->update_record('lesson_default', $default); - } else { - $DB->insert_record('lesson_default', $default); - } - } - unset($lesson->lessondefault); } /** @@ -643,7 +612,8 @@ function lesson_process_post_save(&$lesson) { if ($events = $DB->get_records('event', array('modulename'=>'lesson', 'instance'=>$lesson->id))) { foreach($events as $event) { - delete_event($event->id); + $event = calendar_event::load($event->id); + $event->delete(); } } @@ -664,20 +634,18 @@ function lesson_process_post_save(&$lesson) { if ($lesson->deadline and $lesson->available and $event->timeduration <= LESSON_MAX_EVENT_LENGTH) { // Single event for the whole lesson. $event->name = $lesson->name; - add_event($event); + calendar_event::create(clone($event)); } else { // Separate start and end events. $event->timeduration = 0; if ($lesson->available) { $event->name = $lesson->name.' ('.get_string('lessonopens', 'lesson').')'; - add_event($event); - unset($event->id); // So we can use the same object for the close event. - } - if ($lesson->deadline) { + calendar_event::create(clone($event)); + } else if ($lesson->deadline) { $event->name = $lesson->name.' ('.get_string('lessoncloses', 'lesson').')'; $event->timestart = $lesson->deadline; $event->eventtype = 'close'; - add_event($event); + calendar_event::create(clone($event)); } } } @@ -802,7 +770,7 @@ function lesson_supports($feature) { } /** - * This fucntion extends the global navigaiton for the site. + * This function extends the global navigaiton for the site. * It is important to note that you should not rely on PAGE objects within this * body of code as there is no guarantee that during an AJAX request they are * available @@ -838,6 +806,10 @@ function lesson_extend_settings_navigation($settings, $module) { $lessonnav = $settings->get($lessonnavkey); $lessonnav->forceopen = true; + if (empty($PAGE->cm->context)) { + $PAGE->cm->context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->instance); + } + $canedit = has_capability('mod/lesson:edit', $PAGE->cm->context); $url = new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id)); @@ -875,3 +847,2274 @@ function lesson_extend_settings_navigation($settings, $module) { $settings->remove_child($lessonnavkey); } } + +/** + * Get list of available import or export formats + * + * Copied and modified from lib/questionlib.php + * + * @param string $type 'import' if import list, otherwise export list assumed + * @return array sorted list of import/export formats available + */ +function lesson_get_import_export_formats($type) { + global $CFG; + $fileformats = get_plugin_list("qformat"); + + $fileformatname=array(); + foreach ($fileformats as $fileformat=>$fdir) { + $format_file = "$fdir/format.php"; + if (file_exists($format_file) ) { + require_once($format_file); + } else { + continue; + } + $classname = "qformat_$fileformat"; + $format_class = new $classname(); + if ($type=='import') { + $provided = $format_class->provide_import(); + } else { + $provided = $format_class->provide_export(); + } + if ($provided) { + $formatname = get_string($fileformat, 'quiz'); + if ($formatname == "[[$fileformat]]") { + $formatname = get_string($fileformat, 'qformat_'.$fileformat); + if ($formatname == "[[$fileformat]]") { + $formatname = $fileformat; // Just use the raw folder name + } + } + $fileformatnames[$fileformat] = $formatname; + } + } + natcasesort($fileformatnames); + + return $fileformatnames; +} + +/** + * Serves the lesson attachments. Implements needed access control ;-) + * + * @param object $course + * @param object $cminfo + * @param object $context + * @param string $filearea + * @param array $args + * @param bool $forcedownload + * @return bool false if file not found, does not return if found - justsend the file + */ +function lesson_pluginfile($course, $cminfo, $context, $filearea, $args, $forcedownload) { + global $CFG, $DB; + + if (!$cminfo->uservisible) { + return false; + } + + $fileareas = lesson_get_file_areas(); + if (!array_key_exists($filearea, $fileareas)) { + return false; + } + + if (!$cm = get_coursemodule_from_instance('lesson', $cminfo->instance, $course->id)) { + return false; + } + + if (!$lesson = $DB->get_record('lesson', array('id'=>$cminfo->instance))) { + return false; + } + + require_course_login($course, true, $cm); + + if ($filearea === 'lesson_page_content') { + $pageid = (int)array_shift($args); + if (!$page = $DB->get_record('lesson_pages', array('id'=>$pageid))) { + return false; + } + $fullpath = $context->id.$filearea.$pageid.'/'.implode('/', $args); + $forcedownload = true; + } else { + $fullpath = $context->id.$filearea.implode('/', $args); + } + + $fs = get_file_storage(); + if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { + return false; + } + + // finally send the file + send_stored_file($file, 0, 0, $forcedownload); // download MUST be forced - security! +} + +/** + * Returns an array of file areas + * @return array + */ +function lesson_get_file_areas() { + return array('lesson_page_contents'=>'lesson_page_contents', 'lesson_media_file'=>'lesson_media_file'); +} + +/** + * Returns a file_info_stored object for the file being requested here + * + * @global $CFG + * @param file_browse $browser + * @param array $areas + * @param object $course + * @param object $cm + * @param object $context + * @param string $filearea + * @param int $itemid + * @param string $filepath + * @param string $filename + * @return file_info_stored + */ +function lesson_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { + global $CFG; + $fs = get_file_storage(); + $filepath = is_null($filepath) ? '/' : $filepath; + $filename = is_null($filename) ? '.' : $filename; + $urlbase = $CFG->wwwroot.'/pluginfile.php'; + if (!$storedfile = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) { + return null; + } + return new file_info_stored($browser, $context, $storedfile, $urlbase, $filearea, $itemid, true, true, false); +} + +/** + * This is a function used to detect media types and generate html code. + * + * @global object $CFG + * @global object $PAGE + * @param object $lesson + * @param object $context + * @return string $code the html code of media + */ +function lesson_get_media_html($lesson, $context) { + global $CFG, $PAGE, $OUTPUT; + + // get the media file from file pool + $browser = get_file_browser(); + $file_info = $browser->get_file_info($context, 'lesson_media_file', $lesson->id, '/', $lesson->mediafile); + $url = $file_info->get_url(); + $title = $lesson->mediafile; + + $clicktoopen = $OUTPUT->link(new moodle_url($url), get_string('download')); + + $mimetype = resourcelib_guess_url_mimetype($url); + + // find the correct type and print it out + if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // It's an image + $code = resourcelib_embed_image($url, $title); + + } else if ($mimetype == 'audio/mp3') { + // MP3 audio file + $code = resourcelib_embed_mp3($url, $title, $clicktoopen); + + } else if ($mimetype == 'video/x-flv') { + // Flash video file + $code = resourcelib_embed_flashvideo($url, $title, $clicktoopen); + + } else if ($mimetype == 'application/x-shockwave-flash') { + // Flash file + $code = resourcelib_embed_flash($url, $title, $clicktoopen); + + } else if (substr($mimetype, 0, 10) == 'video/x-ms') { + // Windows Media Player file + $code = resourcelib_embed_mediaplayer($url, $title, $clicktoopen); + + } else if ($mimetype == 'video/quicktime') { + // Quicktime file + $code = resourcelib_embed_quicktime($url, $title, $clicktoopen); + + } else if ($mimetype == 'video/mpeg') { + // Mpeg file + $code = resourcelib_embed_mpeg($url, $title, $clicktoopen); + + } else if ($mimetype == 'audio/x-pn-realaudio-plugin') { + // RealMedia file + $code = resourcelib_embed_real($url, $title, $clicktoopen); + + } else { + // anything else - just try object tag enlarged as much as possible + $code = resourcelib_embed_general($url, $title, $clicktoopen, $mimetype); + $PAGE->requires->yui_lib('dom'); + $PAGE->requires->js('mod/url/functions.js'); + $PAGE->requires->js_function_call('imscp_setup_object')->on_dom_ready(); + } + + return $code; +} + +/** + * Abstract class to provide a core functions to the all lesson classes + * + * This class should be abstracted by ALL classes with the lesson module to ensure + * that all classes within this module can be interacted with in the same way. + * + * This class provides the user with a basic properties array that can be fetched + * or set via magic methods, or alternativily by defining methods get_blah() or + * set_blah() within the extending object. + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class lesson_base { + + /** + * An object containing properties + * @var stdClass + */ + protected $properties; + + /** + * The constructor + * @param stdClass $properties + */ + public function __construct($properties) { + $this->properties = (object)$properties; + } + + /** + * Magic property method + * + * Attempts to call a set_$key method if one exists otherwise falls back + * to simply set the property + * + * @param string $key + * @param mixed $value + */ + public function __set($key, $value) { + if (method_exists($this, 'set_'.$key)) { + $this->{'set_'.$key}($value); + } + $this->properties->{$key} = $value; + } + + /** + * Magic get method + * + * Attempts to call a get_$key method to return the property and ralls over + * to return the raw property + * + * @param str $key + * @return mixed + */ + public function __get($key) { + if (method_exists($this, 'get_'.$key)) { + return $this->{'get_'.$key}(); + } + return $this->properties->{$key}; + } + + /** + * Stupid PHP needs an isset magic method if you use the get magic method and + * still want empty calls to work.... blah ~! + * + * @param string $key + * @return bool + */ + public function __isset($key) { + if (method_exists($this, 'get_'.$key)) { + $val = $this->{'get_'.$key}(); + return !empty($val); + } + return !empty($this->properties->{$key}); + } + + /** + * If overriden should create a new instance, save it in the DB and return it + */ + public static function create() {} + /** + * If overriden should load an instance from the DB and return it + */ + public static function load() {} + /** + * Fetches all of the properties of the object + * @return stdClass + */ + public function properties() { + return $this->properties; + } +} + +/** + * Class representation of a lesson + * + * This class is used the interact with, and manage a lesson once instantiated. + * If you need to fetch a lesson object you can do so by calling + * + * + * lesson::load($lessonid); + * // or + * $lessonrecord = $DB->get_record('lesson', $lessonid); + * $lesson = new lesson($lessonrecord); + * + * + * The class itself extends lesson_base as all classes within the lesson module should + * + * These properties are from the database + * @property int $id The id of this lesson + * @property int $course The ID of the course this lesson belongs to + * @property string $name The name of this lesson + * @property int $practice Flag to toggle this as a practice lesson + * @property int $modattempts Toggle to allow the user to go back and review answers + * @property int $usepassword Toggle the use of a password for entry + * @property string $password The password to require users to enter + * @property int $dependency ID of another lesson this lesson is dependant on + * @property string $conditions Conditions of the lesson dependency + * @property int $grade The maximum grade a user can achieve (%) + * @property int $custom Toggle custom scoring on or off + * @property int $ongoing Toggle display of an ongoing score + * @property int $usemaxgrade How retakes are handled (max=1, mean=0) + * @property int $maxanswers The max number of answers or branches + * @property int $maxattempts The maximum number of attempts a user can record + * @property int $review Toggle use or wrong answer review button + * @property int $nextpagedefault Override the default next page + * @property int $feedback Toggles display of default feedback + * @property int $minquestions Sets a minimum value of pages seen when calculating grades + * @property int $maxpages Maximum number of pages this lesson can contain + * @property int $retake Flag to allow users to retake a lesson + * @property int $activitylink Relate this lesson to another lesson + * @property string $mediafile File to pop up to or webpage to display + * @property int $mediaheight Sets the height of the media file popup + * @property int $mediawidth Sets the width of the media file popup + * @property int $mediaclose Toggle display of a media close button + * @property int $slideshow Flag for whether branch pages should be shown as slideshows + * @property int $width Width of slideshow + * @property int $height Height of slideshow + * @property string $bgcolor Background colour of slideshow + * @property int $displayleft Display a left meun + * @property int $displayleftif Sets the condition on which the left menu is displayed + * @property int $progressbar Flag to toggle display of a lesson progress bar + * @property int $highscores Flag to toggle collection of high scores + * @property int $maxhighscores Number of high scores to limit to + * @property int $available Timestamp of when this lesson becomes available + * @property int $deadline Timestamp of when this lesson is no longer available + * @property int $timemodified Timestamp when lesson was last modified + * + * These properties are calculated + * @property int $firstpageid Id of the first page of this lesson (prevpageid=0) + * @property int $lastpageid Id of the last page of this lesson (nextpageid=0) + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lesson extends lesson_base { + + /** + * The id of the first page (where prevpageid = 0) gets set and retrieved by + * {@see get_firstpageid()} by directly calling $lesson->firstpageid; + * @var int + */ + protected $firstpageid = null; + /** + * The id of the last page (where nextpageid = 0) gets set and retrieved by + * {@see get_lastpageid()} by directly calling $lesson->lastpageid; + * @var int + */ + protected $lastpageid = null; + /** + * An array used to cache the pages associated with this lesson after the first + * time they have been loaded. + * A note to developers: If you are going to be working with MORE than one or + * two pages from a lesson you should probably call {@see $lesson->load_all_pages()} + * in order to save excess database queries. + * @var array An array of lesson_page objects + */ + protected $pages = array(); + /** + * Flag that gets set to true once all of the pages associated with the lesson + * have been loaded. + * @var bool + */ + protected $loadedallpages = false; + + /** + * Simply generates a lesson object given an array/object of properties + * Overrides {@see lesson_base->create()} + * @static + * @param object|array $properties + * @return lesson + */ + public static function create($properties) { + return new lesson($properties); + } + + /** + * Generates a lesson object from the database given its id + * @static + * @param int $lessonid + * @return lesson + */ + public static function load($lessonid) { + if (!$lesson = $DB->get_record('lesson', array('id' => $lessonid))) { + print_error('invalidcoursemodule'); + } + return new lesson($lesson); + } + + /** + * Deletes this lesson from the database + */ + public function delete() { + global $CFG, $DB; + require_once($CFG->libdir.'/gradelib.php'); + + $DB->delete_records("lesson", array("id"=>$this->properties->id));; + $DB->delete_records("lesson_pages", array("lessonid"=>$this->properties->id)); + $DB->delete_records("lesson_answers", array("lessonid"=>$this->properties->id)); + $DB->delete_records("lesson_attempts", array("lessonid"=>$this->properties->id)); + $DB->delete_records("lesson_grades", array("lessonid"=>$this->properties->id)); + $DB->delete_records("lesson_timer", array("lessonid"=>$this->properties->id)); + $DB->delete_records("lesson_branch", array("lessonid"=>$this->properties->id)); + $DB->delete_records("lesson_high_scores", array("lessonid"=>$this->properties->id)); + if ($events = $DB->get_records('event', array("modulename"=>'lesson', "instance"=>$this->properties->id))) { + foreach($events as $event) { + $event = calendar_event::load($event); + $event->delete(); + } + } + + grade_update('mod/lesson', $this->properties->course, 'mod', 'lesson', $this->properties->id, 0, NULL, array('deleted'=>1)); + return true; + } + + /** + * Fetches messages from the session that may have been set in previous page + * actions. + * + * + * // Do not call this method directly instead use + * $lesson->messages; + * + * + * @return array + */ + protected function get_messages() { + global $SESSION; + + $messages = array(); + if (!empty($SESSION->lesson_messages) && is_array($SESSION->lesson_messages) && array_key_exists($this->properties->id, $SESSION->lesson_messages)) { + $messages = $SESSION->lesson_messages[$this->properties->id]; + unset($SESSION->lesson_messages[$this->properties->id]); + } + + return $messages; + } + + /** + * Get all of the attempts for the current user. + * + * @param int $retries + * @param bool $correct Optional: only fetch correct attempts + * @param int $pageid Optional: only fetch attempts at the given page + * @param int $userid Optional: defaults to the current user if not set + * @return array|false + */ + public function get_attempts($retries, $correct=false, $pageid=null, $userid=null) { + global $USER, $DB; + $params = array("lessonid"=>$this->properties->id, "userid"=>$userid, "retry"=>$retries); + if ($correct) { + $params['correct'] = 1; + } + if ($pageid !== null) { + $params['pageid'] = $pageid; + } + if ($userid === null) { + $params['userid'] = $USER->id; + } + return $DB->get_records('lesson_attempts', $params, 'timeseen DESC'); + } + + /** + * Returns the first page for the lesson or false if there isn't one. + * + * This method should be called via the magic method __get(); + * + * $firstpage = $lesson->firstpage; + * + * + * @return lesson_page|bool Returns the lesson_page specialised object or false + */ + protected function get_firstpage() { + $pages = $this->load_all_pages(); + if (count($pages) > 0) { + foreach ($pages as $page) { + if ((int)$page->prevpageid === 0) { + return $page; + } + } + } + return false; + } + + /** + * Returns the last page for the lesson or false if there isn't one. + * + * This method should be called via the magic method __get(); + * + * $lastpage = $lesson->lastpage; + * + * + * @return lesson_page|bool Returns the lesson_page specialised object or false + */ + protected function get_lastpage() { + $pages = $this->load_all_pages(); + if (count($pages) > 0) { + foreach ($pages as $page) { + if ((int)$page->nextpageid === 0) { + return $page; + } + } + } + return false; + } + + /** + * Returns the id of the first page of this lesson. (prevpageid = 0) + * @return int + */ + protected function get_firstpageid() { + global $DB; + if ($this->firstpageid == null) { + if (!$this->loadedallpages) { + $firstpageid = $DB->get_field('lesson_pages', 'id', array('lessonid'=>$this->properties->id, 'prevpageid'=>0)); + if (!$firstpageid) { + print_error('cannotfindfirstpage', 'lesson'); + } + $this->firstpageid = $firstpageid; + } else { + $firstpage = $this->get_firstpage(); + $this->firstpageid = $firstpage->id; + } + } + return $this->firstpageid; + } + + /** + * Returns the id of the last page of this lesson. (nextpageid = 0) + * @return int + */ + public function get_lastpageid() { + global $DB; + if ($this->lastpageid == null) { + if (!$this->loadedallpages) { + $lastpageid = $DB->get_field('lesson_pages', 'id', array('lessonid'=>$this->properties->id, 'nextpageid'=>0)); + if (!$lastpageid) { + print_error('cannotfindlastpage', 'lesson'); + } + $this->lastpageid = $lastpageid; + } else { + $lastpageid = $this->get_lastpage(); + $this->lastpageid = $lastpageid->id; + } + } + + return $this->lastpageid; + } + + /** + * Gets the next page to display after the one that is provided. + * @param int $nextpageid + * @return bool + */ + public function get_next_page($nextpageid) { + global $USER; + $allpages = $this->load_all_pages(); + if ($this->properties->nextpagedefault) { + // in Flash Card mode...first get number of retakes + shuffle($allpages); + $found = false; + if ($this->properties->nextpagedefault == LESSON_UNSEENPAGE) { + foreach ($allpages as $nextpage) { + if (!$DB->count_records("lesson_attempts", array("pageid"=>$nextpage->id, "userid"=>$USER->id, "retry"=>$nretakes))) { + $found = true; + break; + } + } + } elseif ($this->properties->nextpagedefault == LESSON_UNANSWEREDPAGE) { + foreach ($allpages as $nextpage) { + if (!$DB->count_records("lesson_attempts", array('pageid'=>$nextpage->id, 'userid'=>$USER->id, 'correct'=>1, 'retry'=>$nretakes))) { + $found = true; + break; + } + } + } + if ($found) { + if ($this->properties->maxpages) { + // check number of pages viewed (in the lesson) + $nretakes = $DB->count_records("lesson_grades", array("lessonid"=>$this->properties->id, "userid"=>$USER->id)); + if ($DB->count_records("lesson_attempts", array("lessonid"=>$this->properties->id, "userid"=>$USER->id, "retry"=>$nretakes)) >= $this->properties->maxpages) { + return false; + } + } + return $nextpage; + } + } + // In a normal lesson mode + foreach ($allpages as $nextpage) { + if ((int)$nextpage->id===(int)$nextpageid) { + return $nextpage; + } + } + return false; + } + + /** + * Sets a message against the session for this lesson that will displayed next + * time the lesson processes messages + * + * @param string $message + * @param string $class + * @param string $align + * @return bool + */ + public function add_message($message, $class="notifyproblem", $align='center') { + global $SESSION; + + if (empty($SESSION->lesson_messages) || !is_array($SESSION->lesson_messages)) { + $SESSION->lesson_messages = array(); + $SESSION->lesson_messages[$this->properties->id] = array(); + } else if (!array_key_exists($this->properties->id, $SESSION->lesson_messages)) { + $SESSION->lesson_messages[$this->properties->id] = array(); + } + + $SESSION->lesson_messages[$this->properties->id][] = array($message, $class, $align); + + return true; + } + + /** + * Check if the lesson is accessible at the present time + * @return bool True if the lesson is accessible, false otherwise + */ + public function is_accessible() { + $available = $this->properties->available; + $deadline = $this->properties->deadline; + return (($available == 0 || time() >= $available) && ($deadline == 0 || time() < $deadline)); + } + + /** + * Starts the lesson time for the current user + * @return bool Returns true + */ + public function start_timer() { + global $USER, $DB; + $USER->startlesson[$this->properties->id] = true; + $startlesson = new stdClass; + $startlesson->lessonid = $this->properties->id; + $startlesson->userid = $USER->id; + $startlesson->starttime = time(); + $startlesson->lessontime = time(); + $DB->insert_record('lesson_timer', $startlesson); + if ($this->properties->timed) { + $this->add_message(get_string('maxtimewarning', 'lesson', $this->properties->maxtime), 'center'); + } + return true; + } + + /** + * Updates the timer to the current time and returns the new timer object + * @param bool $restart If set to true the timer is restarted + * @param bool $continue If set to true AND $restart=true then the timer + * will continue from a previous attempt + * @return stdClass The new timer + */ + public function update_timer($restart=false, $continue=false) { + global $USER, $DB; + // clock code + // get time information for this user + if (!$timer = $DB->get_records('lesson_timer', array ("lessonid" => $this->properties->id, "userid" => $USER->id), 'starttime DESC', '*', 0, 1)) { + print_error('cannotfindtimer', 'lesson'); + } else { + $timer = current($timer); // this will get the latest start time record + } + + if ($restart) { + if ($continue) { + // continue a previous test, need to update the clock (think this option is disabled atm) + $timer->starttime = time() - ($timer->lessontime - $timer->starttime); + } else { + // starting over, so reset the clock + $timer->starttime = time(); + } + } + + $timer->lessontime = time(); + $DB->update_record('lesson_timer', $timer); + return $timer; + } + + /** + * Updates the timer to the current time then stops it by unsetting the user var + * @return bool Returns true + */ + public function stop_timer() { + global $USER, $DB; + unset($USER->startlesson[$this->properties->id]); + return $this->update_timer(false, false); + } + + /** + * Checks to see if the lesson has pages + */ + public function has_pages() { + global $DB; + $pagecount = $DB->count_records('lesson_pages', array('lessonid'=>$this->properties->id)); + return ($pagecount>0); + } + + /** + * Returns the link for the related activity + * @return html_link|false + */ + public function link_for_activitylink() { + global $DB; + $module = $DB->get_record('course_modules', array('id' => $this->properties->activitylink)); + if ($module) { + $modname = $DB->get_field('modules', 'name', array('id' => $module->module)); + if ($modname) { + $instancename = $DB->get_field($modname, 'name', array('id' => $module->instance)); + if ($instancename) { + $link = html_link::make(new moodle_url($CFG->wwwroot.'/mod/'.$modname.'/view.php', array('id'=>$this->properties->activitylink)), get_string('returnto', 'lesson', get_string('activitylinkname', 'lesson', $instancename))); + $link->set_classes(array('centerpadded','lessonbutton','standardbutton')); + return $link; + } + } + } + return false; + } + + /** + * Loads the requested page. + * + * This function will return the requested page id as either a specialised + * lesson_page object OR as a generic lesson_page. + * If the page has been loaded previously it will be returned from the pages + * array, otherwise it will be loaded from the database first + * + * @param int $pageid + * @return lesson_page A lesson_page object or an object that extends it + */ + public function load_page($pageid) { + if (!array_key_exists($pageid, $this->pages)) { + $manager = lesson_page_type_manager::get($this); + $this->pages[$pageid] = $manager->load_page($pageid, $this); + } + return $this->pages[$pageid]; + } + + /** + * Loads ALL of the pages for this lesson + * + * @return array An array containing all pages from this lesson + */ + public function load_all_pages() { + if (!$this->loadedallpages) { + $manager = lesson_page_type_manager::get($this); + $this->pages = $manager->load_all_pages($this); + $this->loadedallpages = true; + } + return $this->pages; + } + + /** + * Determins if a jumpto value is correct or not. + * + * returns true if jumpto page is (logically) after the pageid page or + * if the jumpto value is a special value. Returns false in all other cases. + * + * @param int $pageid Id of the page from which you are jumping from. + * @param int $jumpto The jumpto number. + * @return boolean True or false after a series of tests. + **/ + public function jumpto_is_correct($pageid, $jumpto) { + global $DB; + + // first test the special values + if (!$jumpto) { + // same page + return false; + } elseif ($jumpto == LESSON_NEXTPAGE) { + return true; + } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) { + return true; + } elseif ($jumpto == LESSON_RANDOMPAGE) { + return true; + } elseif ($jumpto == LESSON_CLUSTERJUMP) { + return true; + } elseif ($jumpto == LESSON_EOL) { + return true; + } + + $pages = $this->load_all_pages(); + $apageid = $pages[$pageid]->nextpageid; + while ($apageid != 0) { + if ($jumpto == $apageid) { + return true; + } + $apageid = $pages[$apageid]->nextpageid; + } + return false; + } + + /** + * Returns the time a user has remaining on this lesson + * @param int $starttime Starttime timestamp + * @return string + */ + public function time_remaining($starttime) { + $timeleft = $starttime + $this->maxtime * 60 - time(); + $hours = floor($timeleft/3600); + $timeleft = $timeleft - ($hours * 3600); + $minutes = floor($timeleft/60); + $secs = $timeleft - ($minutes * 60); + + if ($minutes < 10) { + $minutes = "0$minutes"; + } + if ($secs < 10) { + $secs = "0$secs"; + } + $output = array(); + $output[] = $hours; + $output[] = $minutes; + $output[] = $secs; + $output = implode(':', $output); + return $output; + } + + /** + * Interprets LESSON_CLUSTERJUMP jumpto value. + * + * This will select a page randomly + * and the page selected will be inbetween a cluster page and end of cluter or end of lesson + * and the page selected will be a page that has not been viewed already + * and if any pages are within a branch table or end of branch then only 1 page within + * the branch table or end of branch will be randomly selected (sub clustering). + * + * @param int $pageid Id of the current page from which we are jumping from. + * @param int $userid Id of the user. + * @return int The id of the next page. + **/ + public function cluster_jump($pageid, $userid=null) { + global $DB, $USER; + + if ($userid===null) { + $userid = $USER->id; + } + // get the number of retakes + if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$this->properties->id, "userid"=>$userid))) { + $retakes = 0; + } + // get all the lesson_attempts aka what the user has seen + $seenpages = array(); + if ($attempts = $this->get_attempts($retakes)) { + foreach ($attempts as $attempt) { + $seenpages[$attempt->pageid] = $attempt->pageid; + } + + } + + // get the lesson pages + $lessonpages = $this->load_all_pages(); + // find the start of the cluster + while ($pageid != 0) { // this condition should not be satisfied... should be a cluster page + if ($lessonpages[$pageid]->qtype == LESSON_PAGE_CLUSTER) { + break; + } + $pageid = $lessonpages[$pageid]->prevpageid; + } + + $clusterpages = array(); + $clusterpages = $this->get_sub_pages_of($pageid, array(LESSON_PAGE_ENDOFCLUSTER)); + $unseen = array(); + foreach ($clusterpages as $key=>$cluster) { + if ($cluster->type !== lesson_page::TYPE_QUESTION) { + unset($clusterpages[$key]); + } elseif ($cluster->is_unseen($seenpages)) { + $unseen[] = $cluster; + } + } + + if (count($unseen) > 0) { + // it does not contain elements, then use exitjump, otherwise find out next page/branch + $nextpage = $unseen[rand(0, count($unseen)-1)]; + if ($nextpage->qtype == LESSON_PAGE_BRANCHTABLE) { + // if branch table, then pick a random page inside of it + $branchpages = $this->get_sub_pages_of($nextpage->id, array(LESSON_PAGE_BRANCHTABLE, LESSON_PAGE_ENDOFBRANCH)); + return $branchpages[rand(0, count($branchpages)-1)]->id; + } else { // otherwise, return the page's id + return $nextpage->id; + } + } else { + // seen all there is to see, leave the cluster + if (end($clusterpages)->nextpageid == 0) { + return LESSON_EOL; + } else { + $clusterendid = $pageid; + while ($clusterendid != 0) { // this condition should not be satisfied... should be a cluster page + if ($lessonpages[$clusterendid]->qtype == LESSON_PAGE_CLUSTER) { + break; + } + $clusterendid = $lessonpages[$clusterendid]->prevpageid; + } + $exitjump = $DB->get_field("lesson_answers", "jumpto", array("pageid" => $clusterendid, "lessonid" => $this->properties->id)); + if ($exitjump == LESSON_NEXTPAGE) { + $exitjump = $lessonpages[$pageid]->nextpageid; + } + if ($exitjump == 0) { + return LESSON_EOL; + } else if (in_array($exitjump, array(LESSON_EOL, LESSON_PREVIOUSPAGE))) { + return $exitjump; + } else { + if (!array_key_exists($exitjump, $lessonpages)) { + $found = false; + foreach ($lessonpages as $page) { + if ($page->id === $clusterendid) { + $found = true; + } else if ($page->qtype == LESSON_PAGE_ENDOFCLUSTER) { + $exitjump = $DB->get_field("lesson_answers", "jumpto", array("pageid" => $page->id, "lessonid" => $this->properties->id)); + break; + } + } + } + if (!array_key_exists($exitjump, $lessonpages)) { + return LESSON_EOL; + } + return $exitjump; + } + } + } + } + + /** + * Finds all pages that appear to be a subtype of the provided pageid until + * an end point specified within $ends is encountered or no more pages exist + * + * @param int $pageid + * @param array $ends An array of LESSON_PAGE_* types that signify an end of + * the subtype + * @return array An array of specialised lesson_page objects + */ + public function get_sub_pages_of($pageid, array $ends) { + $lessonpages = $this->load_all_pages(); + $pageid = $lessonpages[$pageid]->nextpageid; // move to the first page after the branch table + $pages = array(); + + while (true) { + if ($pageid == 0 || in_array($lessonpages[$pageid]->qtype, $ends)) { + break; + } + $pages[] = $lessonpages[$pageid]; + $pageid = $lessonpages[$pageid]->nextpageid; + } + + return $pages; + } + + /** + * Checks to see if the specified page[id] is a subpage of a type specified in + * the $types array, until either there are no more pages of we find a type + * corrosponding to that of a type specified in $ends + * + * @param int $pageid The id of the page to check + * @param array $types An array of types that would signify this page was a subpage + * @param array $ends An array of types that mean this is not a subpage + * @return bool + */ + public function is_sub_page_of_type($pageid, array $types, array $ends) { + $pages = $this->load_all_pages(); + $pageid = $pages[$pageid]->prevpageid; // move up one + + array_unshift($ends, 0); + // go up the pages till branch table + while (true) { + if ($pageid==0 || in_array($pages[$pageid]->qtype, $ends)) { + return false; + } else if (in_array($pages[$pageid]->qtype, $types)) { + return true; + } + $pageid = $pages[$pageid]->prevpageid; + } + } +} + +/** + * Abstract class representation of a page associated with a lesson. + * + * This class should MUST be extended by all specialised page types defined in + * mod/lesson/pagetypes/. + * There are a handful of abstract methods that need to be defined as well as + * severl methods that can optionally be defined in order to make the page type + * operate in the desired way + * + * Database properties + * @property int $id The id of this lesson page + * @property int $lessonid The id of the lesson this page belongs to + * @property int $prevpageid The id of the page before this one + * @property int $nextpageid The id of the next page in the page sequence + * @property int $qtype Identifies the page type of this page + * @property int $qoption Used to record page type specific options + * @property int $layout Used to record page specific layout selections + * @property int $display Used to record page specific display selections + * @property int $timecreated Timestamp for when the page was created + * @property int $timemodified Timestamp for when the page was last modified + * @property string $title The title of this page + * @property string $contents The rich content shown to describe the page + * @property int $contentsformat The format of the contents field + * + * Calculated properties + * @property-read array $answers An array of answers for this page + * @property-read bool $displayinmenublock Toggles display in the left menu block + * @property-read array $jumps An array containing all the jumps this page uses + * @property-read lesson $lesson The lesson this page belongs to + * @property-read int $type The type of the page [question | structure] + * @property-read typeid The unique identifier for the page type + * @property-read typestring The string that describes this page type + * + * @abstract + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class lesson_page extends lesson_base { + + /** + * A reference to the lesson this page belongs to + * @var lesson + */ + protected $lesson = null; + /** + * Contains the answers to this lesson_page once loaded + * @var null|array + */ + protected $answers = null; + /** + * This sets the type of the page, can be one of the constants defined below + * @var int + */ + protected $type = 0; + + /** + * Constants used to identify the type of the page + */ + const TYPE_QUESTION = 0; + const TYPE_STRUCTURE = 1; + + /** + * This method should return the integer used to identify the page type within + * the database and thoughout code. This maps back to the defines used in 1.x + * @abstract + * @return int + */ + abstract protected function get_typeid(); + /** + * This method should return the string that describes the pagetype + * @abstract + * @return string + */ + abstract protected function get_typestring(); + + /** + * This method gets called to display the page to the user taking the lesson + * @abstract + * @param object $renderer + * @param object $attempt + * @return string + */ + abstract public function display($renderer, $attempt); + + /** + * Creates a new lesson_page within the database and returns the correct pagetype + * object to use to interact with the new lesson + * + * @final + * @static + * @param object $properties + * @param lesson $lesson + * @return lesson_page Specialised object that extends lesson_page + */ + final public static function create($properties, lesson $lesson, $context, $maxbytes) { + global $DB; + $newpage = new stdClass; + $newpage->title = $properties->title; + $newpage->contents = $properties->contents_editor['text']; + $newpage->contentsformat = $properties->contents_editor['format']; + $newpage->lessonid = $lesson->id; + $newpage->timecreated = time(); + $newpage->qtype = $properties->qtype; + $newpage->qoption = (isset($properties->qoption))?1:0; + $newpage->layout = (isset($properties->layout))?1:0; + $newpage->display = (isset($properties->display))?1:0; + $newpage->prevpageid = 0; // this is a first page + $newpage->nextpageid = 0; // this is the only page + + if ($properties->pageid) { + $prevpage = $DB->get_record("lesson_pages", array("id" => $properties->pageid), 'id, nextpageid'); + if (!$prevpage) { + print_error('cannotfindpages', 'lesson'); + } + $newpage->prevpageid = $prevpage->id; + $newpage->nextpageid = $prevpage->nextpageid; + } else { + $nextpage = $DB->get_record('lesson_pages', array('lessonid'=>$lesson->id, 'prevpageid'=>0), 'id'); + if ($nextpage) { + // This is the first page, there are existing pages put this at the start + $newpage->nextpageid = $nextpage->id; + } + } + + $newpage->id = $DB->insert_record("lesson_pages", $newpage); + + $editor = new stdClass; + $editor->id = $newpage->id; + $editor->contents_editor = $properties->contents_editor; + $editor = file_postupdate_standard_editor($editor, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$maxbytes), $context, 'lesson_page_contents', $editor->id); + $DB->update_record("lesson_pages", $editor); + + if ($newpage->prevpageid > 0) { + $DB->set_field("lesson_pages", "nextpageid", $newpage->id, array("id" => $newpage->prevpageid)); + } + if ($newpage->nextpageid > 0) { + $DB->set_field("lesson_pages", "prevpageid", $newpage->id, array("id" => $newpage->nextpageid)); + } + + $page = lesson_page::load($newpage, $lesson); + $page->create_answers($properties); + + $lesson->add_message(get_string('insertedpage', 'lesson').': '.format_string($newpage->title, true), 'notifysuccess'); + + return $page; + } + + /** + * This method loads a page object from the database and returns it as a + * specialised object that extends lesson_page + * + * @final + * @static + * @param int $id + * @param lesson $lesson + * @return lesson_page Specialised lesson_page object + */ + final public static function load($id, lesson $lesson) { + global $DB; + + if (is_object($id) && !empty($id->qtype)) { + $page = $id; + } else { + $page = $DB->get_record("lesson_pages", array("id" => $id)); + if (!$page) { + print_error('cannotfindpages', 'lesson'); + } + } + $manager = lesson_page_type_manager::get($lesson); + + $class = 'lesson_page_type_'.$manager->get_page_type_idstring($page->qtype); + if (!class_exists($class)) { + $class = 'lesson_page'; + } + + return new $class($page, $lesson); + } + + /** + * Deletes a lesson_page from the database as well as any associated records. + * @final + * @return bool + */ + final public function delete() { + global $DB; + // first delete all the associated records... + $DB->delete_records("lesson_attempts", array("pageid" => $this->properties->id)); + // ...now delete the answers... + $DB->delete_records("lesson_answers", array("pageid" => $this->properties->id)); + // ..and the page itself + $DB->delete_records("lesson_pages", array("id" => $this->properties->id)); + + // repair the hole in the linkage + if (!$this->properties->prevpageid && !$this->properties->nextpageid) { + //This is the only page, no repair needed + } elseif (!$this->properties->prevpageid) { + // this is the first page... + $page = $this->lesson->load_page($this->properties->nextpageid); + $page->move(null, 0); + } elseif (!$this->properties->nextpageid) { + // this is the last page... + $page = $this->lesson->load_page($this->properties->prevpageid); + $page->move(0); + } else { + // page is in the middle... + $prevpage = $this->lesson->load_page($this->properties->prevpageid); + $nextpage = $this->lesson->load_page($this->properties->nextpageid); + + $prevpage->move($nextpage->id); + $nextpage->move(null, $prevpage->id); + } + return true; + } + + /** + * Moves a page by updating its nextpageid and prevpageid values within + * the database + * + * @final + * @param int $nextpageid + * @param int $prevpageid + */ + final public function move($nextpageid=null, $prevpageid=null) { + global $DB; + if ($nextpageid === null) { + $nextpageid = $this->properties->nextpageid; + } + if ($prevpageid === null) { + $prevpageid = $this->properties->prevpageid; + } + $obj = new stdClass; + $obj->id = $this->properties->id; + $obj->prevpageid = $prevpageid; + $obj->nextpageid = $nextpageid; + $DB->update_record('lesson_pages', $obj); + } + + /** + * Returns the answers that are associated with this page in the database + * + * @final + * @return array + */ + final public function get_answers() { + global $DB; + if ($this->answers === null) { + $this->answers = array(); + $answers = $DB->get_records('lesson_answers', array('pageid'=>$this->properties->id, 'lessonid'=>$this->lesson->id), 'id'); + if (!$answers) { + print_error('cannotfindanswer', 'lesson'); + } + foreach ($answers as $answer) { + $this->answers[count($this->answers)] = new lesson_page_answer($answer); + } + } + return $this->answers; + } + + /** + * Returns the lesson this page is associated with + * @final + * @return lesson + */ + final protected function get_lesson() { + return $this->lesson; + } + + /** + * Returns the type of page this is. Not to be confused with page type + * @final + * @return int + */ + final protected function get_type() { + return $this->type; + } + + /** + * Records an attempt at this page + * + * @final + * @param stdClass $context + * @return stdClass Returns the result of the attempt + */ + final public function record_attempt($context) { + global $DB, $USER, $OUTPUT; + + /** + * This should be overriden by each page type to actually check the response + * against what ever custom criteria they have defined + */ + $result = $this->check_answer(); + + $result->attemptsremaining = 0; + $result->maxattemptsreached = false; + + if ($result->noanswer) { + $result->newpageid = $this->properties->id; // display same page again + $result->feedback = get_string('noanswer', 'lesson'); + } else { + if (!has_capability('mod/lesson:manage', $context)) { + $nretakes = $DB->count_records("lesson_grades", array("lessonid"=>$this->lesson->id, "userid"=>$USER->id)); + // record student's attempt + $attempt = new stdClass; + $attempt->lessonid = $this->lesson->id; + $attempt->pageid = $this->properties->id; + $attempt->userid = $USER->id; + $attempt->answerid = $result->answerid; + $attempt->retry = $nretakes; + $attempt->correct = $result->correctanswer; + if($result->userresponse !== null) { + $attempt->useranswer = $result->userresponse; + } + + $attempt->timeseen = time(); + // if allow modattempts, then update the old attempt record, otherwise, insert new answer record + if (isset($USER->modattempts[$this->lesson->id])) { + $attempt->retry = $nretakes - 1; // they are going through on review, $nretakes will be too high + } + + $DB->insert_record("lesson_attempts", $attempt); + // "number of attempts remaining" message if $this->lesson->maxattempts > 1 + // displaying of message(s) is at the end of page for more ergonomic display + if (!$result->correctanswer && ($result->newpageid == 0)) { + // wrong answer and student is stuck on this page - check how many attempts + // the student has had at this page/question + $nattempts = $DB->count_records("lesson_attempts", array("pageid"=>$this->properties->id, "userid"=>$USER->id),"retry", $nretakes); + // retreive the number of attempts left counter for displaying at bottom of feedback page + if ($nattempts >= $this->lesson->maxattempts) { + if ($this->lesson->maxattempts > 1) { // don't bother with message if only one attempt + $result->maxattemptsreached = true; + } + $result->newpageid = LESSON_NEXTPAGE; + } else if ($this->lesson->maxattempts > 1) { // don't bother with message if only one attempt + $result->attemptsremaining = $this->lesson->maxattempts - $nattempts; + } + } + } + // TODO: merge this code with the jump code below. Convert jumpto page into a proper page id + if ($result->newpageid == 0) { + $result->newpageid = $this->properties->id; + } elseif ($result->newpageid == LESSON_NEXTPAGE) { + $nextpage = $this->lesson->get_next_page($this->properties->nextpageid); + if ($nextpage === false) { + $result->newpageid = LESSON_EOL; + } else { + $result->newpageid = $nextpage->id; + } + } + + // Determine default feedback if necessary + if (empty($result->response)) { + if (!$this->lesson->feedback && !$result->noanswer && !($this->lesson->review & !$result->correctanswer && !$result->isessayquestion)) { + // These conditions have been met: + // 1. The lesson manager has not supplied feedback to the student + // 2. Not displaying default feedback + // 3. The user did provide an answer + // 4. We are not reviewing with an incorrect answer (and not reviewing an essay question) + + $result->nodefaultresponse = true; // This will cause a redirect below + } else if ($result->isessayquestion) { + $result->response = get_string('defaultessayresponse', 'lesson'); + } else if ($result->correctanswer) { + $result->response = get_string('thatsthecorrectanswer', 'lesson'); + } else { + $result->response = get_string('thatsthewronganswer', 'lesson'); + } + } + + if ($result->response) { + if ($this->lesson->review && !$result->correctanswer && !$result->isessayquestion) { + $nretakes = $DB->count_records("lesson_grades", array("lessonid"=>$this->lesson->id, "userid"=>$USER->id)); + $qattempts = $DB->count_records("lesson_attempts", array("userid"=>$USER->id, "retry"=>$nretakes, "pageid"=>$this->properties->id)); + if ($qattempts == 1) { + $result->feedback = get_string("firstwrong", "lesson"); + } else { + $result->feedback = get_string("secondpluswrong", "lesson"); + } + } else { + $class = 'response'; + if ($result->correctanswer) { + $class .= ' correct'; //CSS over-ride this if they exist (!important) + } else if (!$result->isessayquestion) { + $class .= ' incorrect'; //CSS over-ride this if they exist (!important) + } + $options = new stdClass; + $options->noclean = true; + $options->para = true; + $result->feedback = $OUTPUT->box(format_text($this->properties->contents, FORMAT_MOODLE, $options), 'generalbox boxaligncenter'); + $result->feedback .= ''.get_string("youranswer", "lesson").' : '.format_text($result->studentanswer, FORMAT_MOODLE, $options); + $result->feedback .= $OUTPUT->box(format_text($result->response, FORMAT_MOODLE, $options), $class); + } + } + } + + return $result; + } + + /** + * Returns the string for a jump name + * + * @final + * @param int $jumpto Jump code or page ID + * @return string + **/ + final protected function get_jump_name($jumpto) { + global $DB; + static $jumpnames = array(); + + if (!array_key_exists($jumpto, $jumpnames)) { + if ($jumpto == 0) { + $jumptitle = get_string('thispage', 'lesson'); + } elseif ($jumpto == LESSON_NEXTPAGE) { + $jumptitle = get_string('nextpage', 'lesson'); + } elseif ($jumpto == LESSON_EOL) { + $jumptitle = get_string('endoflesson', 'lesson'); + } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) { + $jumptitle = get_string('unseenpageinbranch', 'lesson'); + } elseif ($jumpto == LESSON_PREVIOUSPAGE) { + $jumptitle = get_string('previouspage', 'lesson'); + } elseif ($jumpto == LESSON_RANDOMPAGE) { + $jumptitle = get_string('randompageinbranch', 'lesson'); + } elseif ($jumpto == LESSON_RANDOMBRANCH) { + $jumptitle = get_string('randombranch', 'lesson'); + } elseif ($jumpto == LESSON_CLUSTERJUMP) { + $jumptitle = get_string('clusterjump', 'lesson'); + } else { + if (!$jumptitle = $DB->get_field('lesson_pages', 'title', array('id' => $jumpto))) { + $jumptitle = ''.get_string('notdefined', 'lesson').''; + } + } + $jumpnames[$jumpto] = format_string($jumptitle,true); + } + + return $jumpnames[$jumpto]; + } + + /** + * Construstor method + * @param object $properties + * @param lesson $lesson + */ + public function __construct($properties, lesson $lesson) { + parent::__construct($properties); + $this->lesson = $lesson; + } + + /** + * Returns the score for the attempt + * This may be overriden by page types that require manual grading + * @param array $answers + * @param object $attempt + * @return int + */ + public function earned_score($answers, $attempt) { + return $answers[$attempt->answerid]->score; + } + + /** + * This is a callback method that can be override and gets called when ever a page + * is viewed + * + * @param bool $canmanage True if the user has the manage cap + * @return mixed + */ + public function callback_on_view($canmanage) { + return true; + } + + /** + * Updates a lesson page and its answers within the database + * + * @param object $properties + * @return bool + */ + public function update($properties,$context, $maxbytes) { + global $DB; + $answers = $this->get_answers(); + $properties->id = $this->properties->id; + $properties->lessonid = $this->lesson->id; + if (empty($properties->qoption)) { + $properties->qoption = '0'; + } + $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$maxbytes), $context, 'lesson_page_contents', $properties->id); + $DB->update_record("lesson_pages", $properties); + + for ($i = 0; $i < $this->lesson->maxanswers; $i++) { + if (!array_key_exists($i, $this->answers)) { + $this->answers[$i] = new stdClass; + $this->answers[$i]->lessonid = $this->lesson->id; + $this->answers[$i]->pageid = $this->id; + $this->answers[$i]->timecreated = $this->timecreated; + } + if (!empty($properties->answer[$i])) { + $this->answers[$i]->answer = format_text($properties->answer[$i], FORMAT_PLAIN); + if (isset($properties->response[$i])) { + $this->answers[$i]->response = format_text($properties->response[$i], FORMAT_PLAIN); + } + if (isset($properties->jumpto[$i])) { + $this->answers[$i]->jumpto = $properties->jumpto[$i]; + } + if ($this->lesson->custom && isset($properties->score[$i])) { + $this->answers[$i]->score = $properties->score[$i]; + } + if (!isset($this->answers[$i]->id)) { + $this->answers[$i]->id = $DB->insert_record("lesson_answers", $this->answers[$i]); + } else { + $DB->update_record("lesson_answers", $this->answers[$i]->properties()); + } + + } else { + break; + } + } + return true; + } + + /** + * Can be set to true if the page requires a static link to create a new instance + * instead of simply being included in the dropdown + * @param int $previd + * @return bool + */ + public function add_page_link($previd) { + return false; + } + + /** + * Returns true if a page has been viewed before + * + * @param array|int $param Either an array of pages that have been seen or the + * number of retakes a user has had + * @return bool + */ + public function is_unseen($param) { + global $USER, $DB; + if (is_array($param)) { + $seenpages = $param; + return (!array_key_exists($this->properties->id, $seenpages)); + } else { + $nretakes = $param; + if (!$DB->count_records("lesson_attempts", array("pageid"=>$this->properties->id, "userid"=>$USER->id, "retry"=>$nretakes))) { + return true; + } + } + return false; + } + + /** + * Checks to see if a page has been answered previously + * @param int $nretakes + * @return bool + */ + public function is_unanswered($nretakes) { + global $DB, $USER; + if (!$DB->count_records("lesson_attempts", array('pageid'=>$this->properties->id, 'userid'=>$USER->id, 'correct'=>1, 'retry'=>$nretakes))) { + return true; + } + return false; + } + + /** + * Creates answers within the database for this lesson_page. Usually only ever + * called when creating a new page instance + * @param object $properties + * @return array + */ + public function create_answers($properties) { + global $DB; + // now add the answers + $newanswer = new stdClass; + $newanswer->lessonid = $this->lesson->id; + $newanswer->pageid = $this->properties->id; + $newanswer->timecreated = $this->properties->timecreated; + + $answers = array(); + + for ($i = 0; $i < $this->lesson->maxanswers; $i++) { + $answer = clone($newanswer); + if (!empty($properties->answer[$i])) { + $answer->answer = format_text($properties->answer[$i], FORMAT_PLAIN); + if (isset($properties->response[$i])) { + $answer->response = format_text($properties->response[$i], FORMAT_PLAIN); + } + if (isset($properties->jumpto[$i])) { + $answer->jumpto = $properties->jumpto[$i]; + } + if ($this->lesson->custom && isset($properties->score[$i])) { + $answer->score = $properties->score[$i]; + } + $answer->id = $DB->insert_record("lesson_answers", $answer); + $answers[$answer->id] = new lesson_page_answer($answer); + } else { + break; + } + } + + $this->answers = $answers; + return $answers; + } + + /** + * This method MUST be overriden by all question page types, or page types that + * wish to score a page. + * + * The structure of result should always be the same so it is a good idea when + * overriding this method on a page type to call + * + * $result = parent::check_answer(); + * + * before modifiying it as required. + * + * @return stdClass + */ + public function check_answer() { + $result = new stdClass; + $result->answerid = 0; + $result->noanswer = false; + $result->correctanswer = false; + $result->isessayquestion = false; // use this to turn off review button on essay questions + $result->response = ''; + $result->newpageid = 0; // stay on the page + $result->studentanswer = ''; // use this to store student's answer(s) in order to display it on feedback page + $result->userresponse = null; + $result->feedback = ''; + $result->nodefaultresponse = false; // Flag for redirecting when default feedback is turned off + return $result; + } + + /** + * True if the page uses a custom option + * + * Should be override and set to true if the page uses a custom option. + * + * @return bool + */ + public function has_option() { + return false; + } + + /** + * Returns the maximum number of answers for this page given the maximum number + * of answers permitted by the lesson. + * + * @param int $default + * @return int + */ + public function max_answers($default) { + return $default; + } + + /** + * Returns the properties of this lesson page as an object + * @return stdClass; + */ + public function properties() { + $properties = clone($this->properties); + if ($this->answers === null) { + $this->get_answers(); + } + if (count($this->answers)>0) { + $count = 0; + foreach ($this->answers as $answer) { + $properties->{'answer['.$count.']'} = $answer->answer; + $properties->{'response['.$count.']'} = $answer->response; + $properties->{'jumpto['.$count.']'} = $answer->jumpto; + $properties->{'score['.$count.']'} = $answer->score; + $count++; + } + } + return $properties; + } + + /** + * Returns an array of options to display whn choosing the jumpto for a page/answer + * @static + * @param int $pageid + * @param lesson $lesson + * @return array + */ + public static function get_jumptooptions($pageid, lesson $lesson) { + global $DB; + $jump = array(); + $jump[0] = get_string("thispage", "lesson"); + $jump[LESSON_NEXTPAGE] = get_string("nextpage", "lesson"); + $jump[LESSON_PREVIOUSPAGE] = get_string("previouspage", "lesson"); + $jump[LESSON_EOL] = get_string("endoflesson", "lesson"); + + if ($pageid == 0) { + return $jump; + } + + $pages = $lesson->load_all_pages(); + if ($pages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE || $lesson->is_sub_page_of_type($pageid, array(LESSON_PAGE_BRANCHTABLE), array(LESSON_PAGE_ENDOFBRANCH, LESSON_PAGE_CLUSTER))) { + $jump[LESSON_UNSEENBRANCHPAGE] = get_string("unseenpageinbranch", "lesson"); + $jump[LESSON_RANDOMPAGE] = get_string("randompageinbranch", "lesson"); + } + if($pages[$pageid]->qtype == LESSON_PAGE_CLUSTER || $lesson->is_sub_page_of_type($pageid, array(LESSON_PAGE_CLUSTER), array(LESSON_PAGE_ENDOFCLUSTER))) { + $jump[LESSON_CLUSTERJUMP] = get_string("clusterjump", "lesson"); + } + if (!optional_param('firstpage', 0, PARAM_INT)) { + $apageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0)); + while (true) { + if ($apageid) { + $title = $DB->get_field("lesson_pages", "title", array("id" => $apageid)); + $jump[$apageid] = strip_tags(format_string($title,true)); + $apageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $apageid)); + } else { + // last page reached + break; + } + } + } + return $jump; + } + /** + * Returns the contents field for the page properly formatted and with plugin + * file url's converted + * @return string + */ + public function get_contents() { + global $PAGE; + if (!empty($this->properties->contents)) { + if (!isset($this->properties->contentsformat)) { + $this->properties->contentsformat = FORMAT_HTML; + } + $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); + return file_rewrite_pluginfile_urls($this->properties->contents, 'pluginfile.php', $context->id, 'lesson_page_contents', $this->properties->id); + } else { + return ''; + } + } + + /** + * Set to true if this page should display in the menu block + * @return bool + */ + protected function get_displayinmenublock() { + return false; + } + + /** + * Get the string that describes the options of this page type + * @return string + */ + public function option_description_string() { + return ''; + } + + /** + * Updates a table with the answers for this page + * @param html_table $table + * @return html_table + */ + public function display_answers(html_table $table) { + $answers = $this->get_answers(); + $i = 1; + foreach ($answers as $answer) { + $cells = array(); + $cells[] = "".get_string("jump", "lesson")." $i: "; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + $i++; + } + return $table; + } + + /** + * Determines if this page should be grayed out on the management/report screens + * @return int 0 or 1 + */ + protected function get_grayout() { + return 0; + } + + /** + * Adds stats for this page to the &pagestats object. This should be defined + * for all page types that grade + * @param array $pagestats + * @param int $tries + * @return bool + */ + public function stats(array &$pagestats, $tries) { + return true; + } + + /** + * Formats the answers of this page for a report + * + * @param object $answerpage + * @param object $answerdata + * @param object $useranswer + * @param array $pagestats + * @param int $i Count of first level answers + * @param int $n Count of second level answers + * @return object The answer page for this + */ + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + $data = get_string('jumpsto', 'lesson', $this->get_jump_name($answer->jumpto)); + $answerdata->answers[] = array($data, ""); + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } + + /** + * Gets an array of the jumps used by the answers of this page + * + * @return array + */ + public function get_jumps() { + global $DB; + $jumps = array(); + $params = array ("lessonid" => $this->lesson->id, "pageid" => $this->properties->id); + if ($answers = $this->get_answers()) { + foreach ($answers as $answer) { + $jumps[] = $this->get_jump_name($answer->jumpto); + } + } + return $jumps; + } + /** + * Informs whether this page type require manual grading or not + * @return bool + */ + public function requires_manual_grading() { + return false; + } + + /** + * A callback method that allows a page to override the next page a user will + * see during when this page is being completed. + * @return false|int + */ + public function override_next_page() { + return false; + } + + /** + * This method is used to determine if this page is a valid page + * + * @param array $validpages + * @param array $pageviews + * @return int The next page id to check + */ + public function valid_page_and_view(&$validpages, &$pageviews) { + $validpages[$this->properties->id] = 1; + return $this->properties->nextpageid; + } +} + +/** + * Class used to represent an answer to a page + * + * @property int $id The ID of this answer in the database + * @property int $lessonid The ID of the lesson this answer belongs to + * @property int $pageid The ID of the page this answer belongs to + * @property int $jumpto Identifies where the user goes upon completing a page with this answer + * @property int $grade The grade this answer is worth + * @property int $score The score this answer will give + * @property int $flags Used to store options for the answer + * @property int $timecreated A timestamp of when the answer was created + * @property int $timemodified A timestamp of when the answer was modified + * @property string $answer The answer itself + * @property string $response The response the user sees if selecting this answer + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lesson_page_answer extends lesson_base { + + /** + * Loads an page answer from the DB + * + * @param int $id + * @return lesson_page_answer + */ + public static function load($id) { + global $DB; + $answer = $DB->get_record("lesson_answers", array("id" => $id)); + return new lesson_page_answer($answer); + } + + /** + * Given an object of properties and a page created answer(s) and saves them + * in the database. + * + * @param stdClass $properties + * @param lesson_page $page + * @return array + */ + public static function create($properties, lesson_page $page) { + return $page->create_answers($properties); + } + +} + +/** + * A management class for page types + * + * This class is responsible for managing the different pages. A manager object can + * be retrieved by calling the following line of code: + * + * $manager = lesson_page_type_manager::get($lesson); + * + * The first time the page type manager is retrieved the it includes all of the + * different page types located in mod/lesson/pagetypes. + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class lesson_page_type_manager { + + /** + * An array of different page type classes + * @var array + */ + protected $types = array(); + + /** + * Retrieves the lesson page type manager object + * + * If the object hasn't yet been created it is created here. + * + * @staticvar lesson_page_type_manager $pagetypemanager + * @param lesson $lesson + * @return lesson_page_type_manager + */ + public static function get(lesson $lesson) { + static $pagetypemanager; + if (!($pagetypemanager instanceof lesson_page_type_manager)) { + $pagetypemanager = new lesson_page_type_manager(); + $pagetypemanager->load_lesson_types($lesson); + } + return $pagetypemanager; + } + + /** + * Finds and loads all lesson page types in mod/lesson/pagetypes + * + * @param lesson $lesson + */ + public function load_lesson_types(lesson $lesson) { + global $CFG; + $basedir = $CFG->dirroot.'/mod/lesson/pagetypes/'; + $dir = dir($basedir); + while (false !== ($entry = $dir->read())) { + if (strpos($entry, '.')===0 || !preg_match('#^[a-zA-Z]+\.php#i', $entry)) { + continue; + } + require_once($basedir.$entry); + $class = 'lesson_page_type_'.strtok($entry,'.'); + if (class_exists($class)) { + $pagetype = new $class(new stdClass, $lesson); + $this->types[$pagetype->typeid] = $pagetype; + } + } + + } + + /** + * Returns an array of strings to describe the loaded page types + * + * @param int $type Can be used to return JUST the string for the requested type + * @return array + */ + public function get_page_type_strings($type=null, $special=true) { + $types = array(); + foreach ($this->types as $pagetype) { + if (($type===null || $pagetype->type===$type) && ($special===true || $pagetype->is_standard())) { + $types[$pagetype->typeid] = $pagetype->typestring; + } + } + return $types; + } + + /** + * Returns the basic string used to identify a page type provided with an id + * + * This string can be used to instantiate or identify the page type class. + * If the page type id is unknown then 'unknown' is returned + * + * @param int $id + * @return string + */ + public function get_page_type_idstring($id) { + foreach ($this->types as $pagetype) { + if ((int)$pagetype->typeid === (int)$id) { + return $pagetype->idstring; + } + } + return 'unknown'; + } + + /** + * Loads a page for the provided lesson given it's id + * + * This function loads a page from the lesson when given both the lesson it belongs + * to as well as the page's id. + * If the page doesn't exist an error is thrown + * + * @param int $pageid The id of the page to load + * @param lesson $lesson The lesson the page belongs to + * @return lesson_page A class that extends lesson_page + */ + public function load_page($pageid, lesson $lesson) { + global $DB; + if (!($page =$DB->get_record('lesson_pages', array('id'=>$pageid, 'lessonid'=>$lesson->id)))) { + print_error('cannotfindpages', 'lesson'); + } + $pagetype = get_class($this->types[$page->qtype]); + $page = new $pagetype($page, $lesson); + return $page; + } + + /** + * This function loads ALL pages that belong to the lesson. + * + * @param lesson $lesson + * @return array An array of lesson_page_type_* + */ + public function load_all_pages(lesson $lesson) { + global $DB; + if (!($pages =$DB->get_records('lesson_pages', array('lessonid'=>$lesson->id)))) { + print_error('cannotfindpages', 'lesson'); + } + foreach ($pages as $key=>$page) { + $pagetype = get_class($this->types[$page->qtype]); + $pages[$key] = new $pagetype($page, $lesson); + } + + $orderedpages = array(); + $lastpageid = 0; + + while (true) { + foreach ($pages as $page) { + if ((int)$page->prevpageid === (int)$lastpageid) { + $orderedpages[$page->id] = $page; + unset($pages[$page->id]); + $lastpageid = $page->id; + if ((int)$page->nextpageid===0) { + break 2; + } else { + break 1; + } + } + } + } + + return $orderedpages; + } + + /** + * Fetchs an mform that can be used to create/edit an page + * + * @param int $type The id for the page type + * @param array $arguments Any arguments to pass to the mform + * @return lesson_add_page_form_base + */ + public function get_page_form($type, $arguments) { + $class = 'lesson_add_page_form_'.$this->get_page_type_idstring($type); + if (!class_exists($class) || get_parent_class($class)!=='lesson_add_page_form_base') { + debugging('Lesson page type unknown class requested '.$class, DEBUG_DEVELOPER); + $class = 'lesson_add_page_form_selection'; + } else if ($class === 'lesson_add_page_form_unknown') { + $class = 'lesson_add_page_form_selection'; + } + return new $class(null, $arguments); + } + + /** + * Returns an array of links to use as add page links + * @param int $previd The id of the previous page + * @return array + */ + public function get_add_page_type_links($previd) { + $links = array(); + + foreach ($this->types as $type) { + if (($link = $type->add_page_link($previd)) instanceof html_link) { + $links[] = $link; + } + } + + return $links; + } +} + +/** + * Abstract class that page type's MUST inherit from. + * + * This is the abstract class that ALL add page type forms must extend. + * You will notice that all but two of the methods this class contains are final. + * Essentially the only thing that extending classes can do is extend custom_definition. + * OR if it has a special requirement on creation it can extend construction_override + * + * @abstract + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class lesson_add_page_form_base extends moodleform { + + /** + * This is the classic define that is used to identify this pagetype. + * Will be one of LESSON_* + * @var int + */ + public $qtype; + + /** + * The simple string that describes the page type e.g. truefalse, multichoice + * @var string + */ + public $qtypestring; + + /** + * An array of options used in the htmleditor + * @var array + */ + protected $editoroptions = array(); + + /** + * True if this is a standard page of false if it does something special. + * Questions are standard pages, branch tables are not + * @var bool + */ + protected $standard = true; + + /** + * Each page type can and should override this to add any custom elements to + * the basic form that they want + */ + public function custom_definition() {} + + /** + * Sets the data for the form... but modifies if first for the editor then + * calls the parent method + * + * @param stdClass $data An object containing properties to set + * @param int $pageid + */ + public final function set_data($data, $context=null, $pageid=null) { + $data = file_prepare_standard_editor($data, 'contents', $this->editoroptions, $context, 'lesson_page_contents', $pageid); + parent::set_data($data); + } + + /** + * Used to determine if this is a standard page or a special page + * @return bool + */ + public final function is_standard() { + return (bool)$this->standard; + } + + /** + * Add the required basic elements to the form. + * + * This method adds the basic elements to the form including title and contents + * and then calls custom_definition(); + */ + public final function definition() { + $mform = $this->_form; + $editoroptions = $this->_customdata['editoroptions']; + + $mform->addElement('header', 'qtypeheading', get_string('addaquestionpage', 'lesson', get_string($this->qtypestring, 'lesson'))); + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + if ($this->standard === true) { + $mform->addElement('hidden', 'qtype'); + $mform->setType('qtype', PARAM_TEXT); + + $mform->addElement('text', 'title', get_string("pagetitle", "lesson"), array('size'=>70)); + $mform->setType('title', PARAM_TEXT); + $this->editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$this->_customdata['maxbytes']); + $mform->addElement('editor', 'contents_editor', get_string("pagecontents", "lesson"), null, $this->editoroptions); + $mform->setType('contents_editor', PARAM_CLEANHTML); + } + + $this->custom_definition(); + + if ($this->_customdata['edit'] === true) { + $mform->addElement('hidden', 'edit', 1); + $this->add_action_buttons(get_string('cancel'), get_string("savepage", "lesson")); + } else { + $this->add_action_buttons(get_string('cancel'), get_string("addaquestionpage", "lesson")); + } + } + + /** + * Convenience function: Adds a jumpto select element + * + * @param string $name + * @param string|null $label + * @param int $selected The page to select by default + */ + protected final function add_jumpto($name, $label=null, $selected=LESSON_NEXTPAGE) { + $title = get_string("jump", "lesson"); + if ($label === null) { + $label = $title; + } + if (is_int($name)) { + $name = "jumpto[$name]"; + } + $this->_form->addElement('select', $name, $label, $this->_customdata['jumpto']); + $this->_form->setDefault($name, $selected); + $this->_form->setHelpButton($name, array("jumpto", $title, "lesson")); + } + + /** + * Convenience function: Adds a score input element + * + * @param string $name + * @param string|null $label + * @param mixed $value The default value + */ + protected final function add_score($name, $label=null, $value=null) { + if ($label === null) { + $label = get_string("score", "lesson"); + } + if (is_int($name)) { + $name = "score[$name]"; + } + $this->_form->addElement('text', $name, $label, array('size'=>5)); + if ($value !== null) { + $this->_form->setDefault($name, $value); + } + } + + /** + * Convenience function: Adds a textarea element + * + * @param string $name + * @param int $count The count of the element to add + * @param string|null $label + */ + protected final function add_textarea($name, $count, $label) { + $this->_form->addElement('textarea', $name.'['.$count.']', $label, array('rows'=>5, 'cols'=>70, 'width'=>630, 'height'=>300)); + } + /** + * Convenience function: Adds an answer textarea + * + * @param int $count The count of the element to add + */ + protected final function add_answer($count) { + $this->add_textarea('answer', $count, get_string('answer', 'lesson')); + } + /** + * Convenience function: Adds an response textarea + * + * @param int $count The count of the element to add + */ + protected final function add_response($count) { + $this->add_textarea('response', $count, get_string('response', 'lesson')); + } + + /** + * A function that gets called upon init of this object by the calling script. + * + * This can be used to process an immediate action if required. Currently it + * is only used in special cases by non-standard page types. + * + * @return bool + */ + public function construction_override() { + return true; + } +} \ No newline at end of file diff --git a/mod/lesson/locallib.php b/mod/lesson/locallib.php index 0ef98ef418..e544254b1e 100644 --- a/mod/lesson/locallib.php +++ b/mod/lesson/locallib.php @@ -1,1019 +1,62 @@ . + /** * Local library file for Lesson. These are non-standard functions that are used * only by Lesson. * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ -/** -* Next page -> any page not seen before -*/ -if (!defined("LESSON_UNSEENPAGE")) { - define("LESSON_UNSEENPAGE", 1); // Next page -> any page not seen before -} -/** -* Next page -> any page not answered correctly -*/ -if (!defined("LESSON_UNANSWEREDPAGE")) { - define("LESSON_UNANSWEREDPAGE", 2); // Next page -> any page not answered correctly -} - -/** -* Define different lesson flows for next page -*/ -$LESSON_NEXTPAGE_ACTION = array (0 => get_string("normal", "lesson"), - LESSON_UNSEENPAGE => get_string("showanunseenpage", "lesson"), - LESSON_UNANSWEREDPAGE => get_string("showanunansweredpage", "lesson") ); - -// Lesson jump types defined -// TODO: instead of using define statements, create an array with all the jump values - -/** - * Jump to Next Page - */ -if (!defined("LESSON_NEXTPAGE")) { - define("LESSON_NEXTPAGE", -1); -} -/** - * End of Lesson - */ -if (!defined("LESSON_EOL")) { - define("LESSON_EOL", -9); -} -/** - * Jump to an unseen page within a branch and end of branch or end of lesson - */ -if (!defined("LESSON_UNSEENBRANCHPAGE")) { - define("LESSON_UNSEENBRANCHPAGE", -50); -} -/** - * Jump to Previous Page - */ -if (!defined("LESSON_PREVIOUSPAGE")) { - define("LESSON_PREVIOUSPAGE", -40); -} -/** - * Jump to a random page within a branch and end of branch or end of lesson - */ -if (!defined("LESSON_RANDOMPAGE")) { - define("LESSON_RANDOMPAGE", -60); -} -/** - * Jump to a random Branch - */ -if (!defined("LESSON_RANDOMBRANCH")) { - define("LESSON_RANDOMBRANCH", -70); -} -/** - * Cluster Jump - */ -if (!defined("LESSON_CLUSTERJUMP")) { - define("LESSON_CLUSTERJUMP", -80); -} -/** - * Undefined - */ -if (!defined("LESSON_UNDEFINED")) { - define("LESSON_UNDEFINED", -99); -} - -// Lesson question types defined - -/** - * Short answer question type - */ -if (!defined("LESSON_SHORTANSWER")) { - define("LESSON_SHORTANSWER", "1"); -} -/** - * True/False question type - */ -if (!defined("LESSON_TRUEFALSE")) { - define("LESSON_TRUEFALSE", "2"); -} -/** - * Multichoice question type - * - * If you change the value of this then you need - * to change it in restorelib.php as well. - */ -if (!defined("LESSON_MULTICHOICE")) { - define("LESSON_MULTICHOICE", "3"); -} -/** - * Random question type - not used - */ -if (!defined("LESSON_RANDOM")) { - define("LESSON_RANDOM", "4"); -} -/** - * Matching question type - * - * If you change the value of this then you need - * to change it in restorelib.php, in mysql.php - * and postgres7.php as well. - */ -if (!defined("LESSON_MATCHING")) { - define("LESSON_MATCHING", "5"); -} -/** - * Not sure - not used - */ -if (!defined("LESSON_RANDOMSAMATCH")) { - define("LESSON_RANDOMSAMATCH", "6"); -} -/** - * Not sure - not used - */ -if (!defined("LESSON_DESCRIPTION")) { - define("LESSON_DESCRIPTION", "7"); -} -/** - * Numerical question type - */ -if (!defined("LESSON_NUMERICAL")) { - define("LESSON_NUMERICAL", "8"); -} -/** - * Multichoice with multianswer question type - */ -if (!defined("LESSON_MULTIANSWER")) { - define("LESSON_MULTIANSWER", "9"); -} -/** - * Essay question type - */ -if (!defined("LESSON_ESSAY")) { - define("LESSON_ESSAY", "10"); -} - -/** - * Lesson question type array. - * Contains all question types used - */ -$LESSON_QUESTION_TYPE = array ( LESSON_MULTICHOICE => get_string("multichoice", "quiz"), - LESSON_TRUEFALSE => get_string("truefalse", "quiz"), - LESSON_SHORTANSWER => get_string("shortanswer", "quiz"), - LESSON_NUMERICAL => get_string("numerical", "quiz"), - LESSON_MATCHING => get_string("match", "quiz"), - LESSON_ESSAY => get_string("essay", "lesson") -// LESSON_DESCRIPTION => get_string("description", "quiz"), -// LESSON_RANDOM => get_string("random", "quiz"), -// LESSON_RANDOMSAMATCH => get_string("randomsamatch", "quiz"), -// LESSON_MULTIANSWER => get_string("multianswer", "quiz"), - ); - -// Non-question page types - -/** - * Branch Table page - */ -if (!defined("LESSON_BRANCHTABLE")) { - define("LESSON_BRANCHTABLE", "20"); -} -/** - * End of Branch page - */ -if (!defined("LESSON_ENDOFBRANCH")) { - define("LESSON_ENDOFBRANCH", "21"); -} -/** - * Start of Cluster page - */ -if (!defined("LESSON_CLUSTER")) { - define("LESSON_CLUSTER", "30"); -} -/** - * End of Cluster page - */ -if (!defined("LESSON_ENDOFCLUSTER")) { - define("LESSON_ENDOFCLUSTER", "31"); -} - -// other variables... - -/** - * Flag for the editor for the answer textarea. - */ -if (!defined("LESSON_ANSWER_EDITOR")) { - define("LESSON_ANSWER_EDITOR", "1"); -} -/** - * Flag for the editor for the response textarea. - */ -if (!defined("LESSON_RESPONSE_EDITOR")) { - define("LESSON_RESPONSE_EDITOR", "2"); -} +/** Make sure this isn't being directly accessed */ +if (!defined('MOODLE_INTERNAL')) { + die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page. +} + +/** Include the files that are required by this module */ +require_once($CFG->dirroot . '/mod/lesson/lib.php'); + +/** Next page -> any page not seen before */ +define("LESSON_UNSEENPAGE", 1); +/** Next page -> any page not answered correctly */ +define("LESSON_UNANSWEREDPAGE", 2); +/** Jump to Next Page */ +define("LESSON_NEXTPAGE", -1); +/** End of Lesson */ +define("LESSON_EOL", -9); +/** Jump to an unseen page within a branch and end of branch or end of lesson */ +define("LESSON_UNSEENBRANCHPAGE", -50); +/** Jump to Previous Page */ +define("LESSON_PREVIOUSPAGE", -40); +/** Jump to a random page within a branch and end of branch or end of lesson */ +define("LESSON_RANDOMPAGE", -60); +/** Jump to a random Branch */ +define("LESSON_RANDOMBRANCH", -70); +/** Cluster Jump */ +define("LESSON_CLUSTERJUMP", -80); +/** Undefined */ +define("LESSON_UNDEFINED", -99); ////////////////////////////////////////////////////////////////////////////////////// /// Any other lesson functions go here. Each of them must have a name that /// starts with lesson_ -/** - * Print the standard header for lesson module - * - * This will also print up to three - * buttons in the breadcrumb, lesson heading - * lesson tabs, lesson notifications and perhaps - * a popup with a media file. - * - * @param object $cm Course module record object - * @param object $course Course record object - * @param object $lesson Lesson record object - * @param string $currenttab Current tab for the lesson tabs - * @param boolean $extraeditbuttons Show the extra edit buttons next to the 'Update this lesson' button. - * @param integer $lessonpageid if $extraeditbuttons is true then you must pass the page id here. - **/ -function lesson_print_header($cm, $course, $lesson, $currenttab = '', $extraeditbuttons = false, $lessonpageid = NULL) { - global $CFG, $PAGE, $OUTPUT; - - $activityname = format_string($lesson->name, true, $course->id); - - if (empty($title)) { - $title = "{$course->shortname}: $activityname"; - } - -/// Build the buttons - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - if (has_capability('mod/lesson:edit', $context)) { - $buttons = $OUTPUT->update_module_button($cm->id, 'lesson'); - if ($extraeditbuttons) { - if ($lessonpageid === NULL) { - print_error('invalidpageid', 'lesson'); - } - if (!empty($lessonpageid) and $lessonpageid != LESSON_EOL) { - $buttons .= '
      frametarget.' method="get" action="'.$CFG->wwwroot.'/mod/lesson/lesson.php">'. - ''. - ''. - ''. - ''. - ''. - '
      '; - } - $buttons = '' . $buttons .''; - } - } else { - $buttons = ' '; - } - -/// Header setup - $PAGE->set_title($title); - $PAGE->set_heading($course->fullname); - $PAGE->set_button($buttons); - echo $OUTPUT->header(); - - if (has_capability('mod/lesson:manage', $context)) { - - $helpicon = new moodle_help_icon(); - $helpicon->text = $activityname; - $helpicon->page = "overview"; - $helpicon->module = "lesson"; - - echo $OUTPUT->heading_with_help($helpicon); - - if (!empty($currenttab)) { - include($CFG->dirroot.'/mod/lesson/tabs.php'); - } - } else { - echo $OUTPUT->heading($activityname); - } - - lesson_print_messages(); -} - -/** - * Returns course module, course and module instance given - * either the course module ID or a lesson module ID. - * - * @param int $cmid Course Module ID - * @param int $lessonid Lesson module instance ID - * @return array array($cm, $course, $lesson) - **/ -function lesson_get_basics($cmid = 0, $lessonid = 0) { - global $DB; - - if ($cmid) { - if (!$cm = get_coursemodule_from_id('lesson', $cmid)) { - print_error('invalidcoursemodule'); - } - if (!$course = $DB->get_record('course', array('id' => $cm->course))) { - print_error('coursemisconf'); - } - if (!$lesson = $DB->get_record('lesson', array('id' => $cm->instance))) { - print_error('invalidcoursemodule'); - } - } else if ($lessonid) { - if (!$lesson = $DB->get_record('lesson', array('id' => $lessonid))) { - print_error('invalidcoursemodule'); - } - if (!$course = $DB->get_record('course', array('id' => $lesson->course))) { - print_error('coursemisconf'); - } - if (!$cm = get_coursemodule_from_instance('lesson', $lesson->id, $course->id)) { - print_error('invalidcoursemodule'); - } - } else { - print_error('invalidid', 'lesson'); - } - - return array($cm, $course, $lesson); -} - -/** - * Sets a message to be printed. Messages are printed - * by calling {@link lesson_print_messages()}. - * - * @uses $SESSION - * @param string $message The message to be printed - * @param string $class Class to be passed to {@link notify()}. Usually notifyproblem or notifysuccess. - * @param string $align Alignment of the message - * @return boolean - **/ -function lesson_set_message($message, $class="notifyproblem", $align='center') { - global $SESSION; - - if (empty($SESSION->lesson_messages) or !is_array($SESSION->lesson_messages)) { - $SESSION->lesson_messages = array(); - } - - $SESSION->lesson_messages[] = array($message, $class, $align); - - return true; -} - -/** - * Print all set messages. - * - * See {@link lesson_set_message()} for setting messages. - * - * Uses {@link notify()} to print the messages. - * - * @uses $SESSION - * @return boolean - **/ -function lesson_print_messages() { - global $SESSION, $OUTPUT; - - if (empty($SESSION->lesson_messages)) { - // No messages to print - return true; - } - - foreach($SESSION->lesson_messages as $message) { - echo $OUTPUT->notification($message[0], $message[1], $message[2]); - } - - // Reset - unset($SESSION->lesson_messages); - - return true; -} - -/** - * Prints a lesson link that submits a form. - * - * If Javascript is disabled, then a regular submit button is printed - * - * @param string $name Name of the link or button - * @param string $form The name of the form to be submitted - * @param string $align Alignment of the button - * @param string $class Class names to add to the div wrapper - * @param string $title Title for the link (Not used if javascript is disabled) - * @param string $id ID tag - * @param boolean $return Return flag - * @return mixed boolean/html - **/ -function lesson_print_submit_link($name, $form, $align = 'center', $class='standardbutton', $title = '', $id = '', $return = false) { - if (!empty($align)) { - $align = " style=\"text-align:$align\""; - } - if (!empty($id)) { - $id = " id=\"$id\""; - } - if (empty($title)) { - $title = $name; - } - - $output = "
      \n"; - $output .= ""; - $output .= "
      \n"; - - if ($return) { - return $output; - } else { - echo $output; - return true; - } -} - -/** - * Prints a time remaining in the following format: H:MM:SS - * - * @param int $starttime Time when the lesson started - * @param int $maxtime Length of the lesson - * @param boolean $return Return output switch - * @return mixed boolean/string - **/ -function lesson_print_time_remaining($starttime, $maxtime, $return = false) { - // Calculate hours, minutes and seconds - $timeleft = $starttime + $maxtime * 60 - time(); - $hours = floor($timeleft/3600); - $timeleft = $timeleft - ($hours * 3600); - $minutes = floor($timeleft/60); - $secs = $timeleft - ($minutes * 60); - - if ($minutes < 10) { - $minutes = "0$minutes"; - } - if ($secs < 10) { - $secs = "0$secs"; - } - $output = array(); - $output[] = $hours; - $output[] = $minutes; - $output[] = $secs; - - $output = implode(':', $output); - - if ($return) { - return $output; - } else { - echo $output; - return true; - } -} - -/** - * Prints the page action buttons - * - * Move/Edit/Preview/Delete - * - * @uses $CFG - * @param int $cmid Course Module ID - * @param object $page Page record - * @param boolean $printmove Flag to print the move button or not - * @param boolean $printaddpage Flag to print the add page drop-down or not - * @param boolean $return Return flag - * @return mixed boolean/string - **/ -function lesson_print_page_actions($cmid, $page, $printmove, $printaddpage = false, $return = false) { - global $CFG, $OUTPUT; - - $context = get_context_instance(CONTEXT_MODULE, $cmid); - $actions = array(); - - if (has_capability('mod/lesson:edit', $context)) { - if ($printmove) { - $actions[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&action=move&pageid=$page->id\"> - old_icon_url('t/move') . "\" class=\"iconsmall\" alt=\"".get_string('move')."\" />\n"; - } - $actions[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&action=editpage&pageid=$page->id\"> - old_icon_url('t/edit') . "\" class=\"iconsmall\" alt=\"".get_string('update')."\" />\n"; - - $actions[] = "wwwroot/mod/lesson/view.php?id=$cmid&pageid=$page->id\"> - old_icon_url('t/preview') . "\" class=\"iconsmall\" alt=\"".get_string('preview')."\" />\n"; - - $actions[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&sesskey=".sesskey()."&action=confirmdelete&pageid=$page->id\"> - old_icon_url('t/delete') . "\" class=\"iconsmall\" alt=\"".get_string('delete')."\" />\n"; - - if ($printaddpage) { - // Add page drop-down - $options = array(); - $options['addcluster&sesskey='.sesskey()] = get_string('clustertitle', 'lesson'); - $options['addendofcluster&sesskey='.sesskey()] = get_string('endofclustertitle', 'lesson'); - $options['addbranchtable'] = get_string('branchtable', 'lesson'); - $options['addendofbranch&sesskey='.sesskey()] = get_string('endofbranch', 'lesson'); - $options['addpage'] = get_string('question', 'lesson'); - // Base url - $common = "$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&pageid=$page->id"; - $select = html_select::make_popup_form($common, 'action', $options, "addpage_$page->id"); - $select->nothinglabel = get_string('addpage', 'lesson').'...'; - - $actions[] = $OUTPUT->select($select); - } - } - - $actions = implode(' ', $actions); - - if ($return) { - return $actions; - } else { - echo $actions; - return false; - } -} - -/** - * Prints the add links in expanded view or single view when editing - * - * @uses $CFG - * @param int $cmid Course Module ID - * @param int $prevpageid Previous page id - * @param boolean $return Return flag - * @return mixed boolean/string - * @todo &pageid does not make sense, it is prevpageid - **/ -function lesson_print_add_links($cmid, $prevpageid, $return = false) { - global $CFG; - - $context = get_context_instance(CONTEXT_MODULE, $cmid); - - $links = ''; - if (has_capability('mod/lesson:edit', $context)) { - $links = array(); - $links[] = "wwwroot/mod/lesson/import.php?id=$cmid&pageid=$prevpageid\">". - get_string('importquestions', 'lesson').''; - - $links[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&sesskey=".sesskey()."&action=addcluster&pageid=$prevpageid\">". - get_string('addcluster', 'lesson').''; - - if ($prevpageid != 0) { - $links[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&sesskey=".sesskey()."&action=addendofcluster&pageid=$prevpageid\">". - get_string('addendofcluster', 'lesson').''; - } - $links[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&action=addbranchtable&pageid=$prevpageid\">". - get_string('addabranchtable', 'lesson').''; - - if ($prevpageid != 0) { - $links[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&sesskey=".sesskey()."&action=addendofbranch&pageid=$prevpageid\">". - get_string('addanendofbranch', 'lesson').''; - } - - $links[] = "wwwroot/mod/lesson/lesson.php?id=$cmid&action=addpage&pageid=$prevpageid\">". - get_string('addaquestionpagehere', 'lesson').''; - - $links = implode(" | \n", $links); - $links = "\n
      \n$links\n
      \n"; - } - - if ($return) { - return $links; - } else { - echo $links; - return true; - } -} - -/** - * Returns the string for a page type - * - * @uses $LESSON_QUESTION_TYPE - * @param int $qtype Page type - * @return string - **/ -function lesson_get_qtype_name($qtype) { - global $LESSON_QUESTION_TYPE; - switch ($qtype) { - case LESSON_ESSAY : - case LESSON_SHORTANSWER : - case LESSON_MULTICHOICE : - case LESSON_MATCHING : - case LESSON_TRUEFALSE : - case LESSON_NUMERICAL : - return $LESSON_QUESTION_TYPE[$qtype]; - break; - case LESSON_BRANCHTABLE : - return get_string("branchtable", "lesson"); - break; - case LESSON_ENDOFBRANCH : - return get_string("endofbranch", "lesson"); - break; - case LESSON_CLUSTER : - return get_string("clustertitle", "lesson"); - break; - case LESSON_ENDOFCLUSTER : - return get_string("endofclustertitle", "lesson"); - break; - default: - return ''; - break; - } -} - -/** - * Returns the string for a jump name - * - * @param int $jumpto Jump code or page ID - * @return string - **/ -function lesson_get_jump_name($jumpto) { - global $DB; - - if ($jumpto == 0) { - $jumptitle = get_string('thispage', 'lesson'); - } elseif ($jumpto == LESSON_NEXTPAGE) { - $jumptitle = get_string('nextpage', 'lesson'); - } elseif ($jumpto == LESSON_EOL) { - $jumptitle = get_string('endoflesson', 'lesson'); - } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) { - $jumptitle = get_string('unseenpageinbranch', 'lesson'); - } elseif ($jumpto == LESSON_PREVIOUSPAGE) { - $jumptitle = get_string('previouspage', 'lesson'); - } elseif ($jumpto == LESSON_RANDOMPAGE) { - $jumptitle = get_string('randompageinbranch', 'lesson'); - } elseif ($jumpto == LESSON_RANDOMBRANCH) { - $jumptitle = get_string('randombranch', 'lesson'); - } elseif ($jumpto == LESSON_CLUSTERJUMP) { - $jumptitle = get_string('clusterjump', 'lesson'); - } else { - if (!$jumptitle = $DB->get_field('lesson_pages', 'title', array('id' => $jumpto))) { - $jumptitle = ''.get_string('notdefined', 'lesson').''; - } - } - - return format_string($jumptitle,true); -} - -/** - * Given some question info and some data about the the answers - * this function parses, organises and saves the question - * - * This is only used when IMPORTING questions and is only called - * from format.php - * Lifted from mod/quiz/lib.php - - * 1. all reference to oldanswers removed - * 2. all reference to quiz_multichoice table removed - * 3. In SHORTANSWER questions usecase is store in the qoption field - * 4. In NUMERIC questions store the range as two answers - * 5. TRUEFALSE options are ignored - * 6. For MULTICHOICE questions with more than one answer the qoption field is true - * - * @param opject $question Contains question data like question, type and answers. - * @return object Returns $result->error or $result->notice. - **/ -function lesson_save_question_options($question) { - global $DB; - - $timenow = time(); - switch ($question->qtype) { - case LESSON_SHORTANSWER: - - $answers = array(); - $maxfraction = -1; - - // Insert all the new answers - foreach ($question->answer as $key => $dataanswer) { - if ($dataanswer != "") { - $answer = new stdClass; - $answer->lessonid = $question->lessonid; - $answer->pageid = $question->id; - if ($question->fraction[$key] >=0.5) { - $answer->jumpto = LESSON_NEXTPAGE; - } - $answer->timecreated = $timenow; - $answer->grade = $question->fraction[$key] * 100; - $answer->answer = $dataanswer; - $answer->response = $question->feedback[$key]; - $answer->id = $DB->insert_record("lesson_answers", $answer); - $answers[] = $answer->id; - if ($question->fraction[$key] > $maxfraction) { - $maxfraction = $question->fraction[$key]; - } - } - } - - - /// Perform sanity checks on fractional grades - if ($maxfraction != 1) { - $maxfraction = $maxfraction * 100; - $result->notice = get_string("fractionsnomax", "quiz", $maxfraction); - return $result; - } - break; - - case LESSON_NUMERICAL: // Note similarities to SHORTANSWER - - $answers = array(); - $maxfraction = -1; - - - // for each answer store the pair of min and max values even if they are the same - foreach ($question->answer as $key => $dataanswer) { - if ($dataanswer != "") { - $answer = new stdClass; - $answer->lessonid = $question->lessonid; - $answer->pageid = $question->id; - $answer->jumpto = LESSON_NEXTPAGE; - $answer->timecreated = $timenow; - $answer->grade = $question->fraction[$key] * 100; - $min = $question->answer[$key] - $question->tolerance[$key]; - $max = $question->answer[$key] + $question->tolerance[$key]; - $answer->answer = $min.":".$max; - // $answer->answer = $question->min[$key].":".$question->max[$key]; original line for min/max - $answer->response = $question->feedback[$key]; - $answer->id = $DB->insert_record("lesson_answers", $answer); - - $answers[] = $answer->id; - if ($question->fraction[$key] > $maxfraction) { - $maxfraction = $question->fraction[$key]; - } - } - } - - /// Perform sanity checks on fractional grades - if ($maxfraction != 1) { - $maxfraction = $maxfraction * 100; - $result->notice = get_string("fractionsnomax", "quiz", $maxfraction); - return $result; - } - break; - - - case LESSON_TRUEFALSE: - - // the truth - $answer->lessonid = $question->lessonid; - $answer->pageid = $question->id; - $answer->timecreated = $timenow; - $answer->answer = get_string("true", "quiz"); - $answer->grade = $question->answer * 100; - if ($answer->grade > 50 ) { - $answer->jumpto = LESSON_NEXTPAGE; - } - if (isset($question->feedbacktrue)) { - $answer->response = $question->feedbacktrue; - } - $true->id = $DB->insert_record("lesson_answers", $answer); - - // the lie - $answer = new stdClass; - $answer->lessonid = $question->lessonid; - $answer->pageid = $question->id; - $answer->timecreated = $timenow; - $answer->answer = get_string("false", "quiz"); - $answer->grade = (1 - (int)$question->answer) * 100; - if ($answer->grade > 50 ) { - $answer->jumpto = LESSON_NEXTPAGE; - } - if (isset($question->feedbackfalse)) { - $answer->response = $question->feedbackfalse; - } - $false->id = $DB->insert_record("lesson_answers", $answer); - - break; - - - case LESSON_MULTICHOICE: - - $totalfraction = 0; - $maxfraction = -1; - - $answers = array(); - - // Insert all the new answers - foreach ($question->answer as $key => $dataanswer) { - if ($dataanswer != "") { - $answer = new stdClass; - $answer->lessonid = $question->lessonid; - $answer->pageid = $question->id; - $answer->timecreated = $timenow; - $answer->grade = $question->fraction[$key] * 100; - // changed some defaults - /* Original Code - if ($answer->grade > 50 ) { - $answer->jumpto = LESSON_NEXTPAGE; - } - Replaced with: */ - if ($answer->grade > 50 ) { - $answer->jumpto = LESSON_NEXTPAGE; - $answer->score = 1; - } - // end Replace - $answer->answer = $dataanswer; - $answer->response = $question->feedback[$key]; - $answer->id = $DB->insert_record("lesson_answers", $answer); - // for Sanity checks - if ($question->fraction[$key] > 0) { - $totalfraction += $question->fraction[$key]; - } - if ($question->fraction[$key] > $maxfraction) { - $maxfraction = $question->fraction[$key]; - } - } - } - - /// Perform sanity checks on fractional grades - if ($question->single) { - if ($maxfraction != 1) { - $maxfraction = $maxfraction * 100; - $result->notice = get_string("fractionsnomax", "quiz", $maxfraction); - return $result; - } - } else { - $totalfraction = round($totalfraction,2); - if ($totalfraction != 1) { - $totalfraction = $totalfraction * 100; - $result->notice = get_string("fractionsaddwrong", "quiz", $totalfraction); - return $result; - } - } - break; - - case LESSON_MATCHING: - - $subquestions = array(); - - $i = 0; - // Insert all the new question+answer pairs - foreach ($question->subquestions as $key => $questiontext) { - $answertext = $question->subanswers[$key]; - if (!empty($questiontext) and !empty($answertext)) { - $answer = new stdClass; - $answer->lessonid = $question->lessonid; - $answer->pageid = $question->id; - $answer->timecreated = $timenow; - $answer->answer = $questiontext; - $answer->response = $answertext; - if ($i == 0) { - // first answer contains the correct answer jump - $answer->jumpto = LESSON_NEXTPAGE; - } - $subquestion->id = $DB->insert_record("lesson_answers", $answer); - $subquestions[] = $subquestion->id; - $i++; - } - } - - if (count($subquestions) < 3) { - $result->notice = get_string("notenoughsubquestions", "quiz"); - return $result; - } - - break; - - - case LESSON_RANDOMSAMATCH: - $options->question = $question->id; - $options->choose = $question->choose; - if ($existing = $DB->get_record("quiz_randomsamatch", array("question" => $options->question))) { - $options->id = $existing->id; - $DB->update_record("quiz_randomsamatch", $options); - } else { - $DB->insert_record("quiz_randomsamatch", $options); - } - break; - - case LESSON_MULTIANSWER: - if (!$oldmultianswers = $DB->get_records("quiz_multianswers", array("question" => $question->id), "id ASC")) { - $oldmultianswers = array(); - } - - // Insert all the new multi answers - foreach ($question->answers as $dataanswer) { - if ($oldmultianswer = array_shift($oldmultianswers)) { // Existing answer, so reuse it - $multianswer = $oldmultianswer; - $multianswer->positionkey = $dataanswer->positionkey; - $multianswer->norm = $dataanswer->norm; - $multianswer->answertype = $dataanswer->answertype; - - if (! $multianswer->answers = quiz_save_multianswer_alternatives - ($question->id, $dataanswer->answertype, - $dataanswer->alternatives, $oldmultianswer->answers)) - { - $result->error = "Could not update multianswer alternatives! (id=$multianswer->id)"; - return $result; - } - $DB->update_record("quiz_multianswers", $multianswer); - } else { // This is a completely new answer - $multianswer = new stdClass; - $multianswer->question = $question->id; - $multianswer->positionkey = $dataanswer->positionkey; - $multianswer->norm = $dataanswer->norm; - $multianswer->answertype = $dataanswer->answertype; - - if (! $multianswer->answers = quiz_save_multianswer_alternatives - ($question->id, $dataanswer->answertype, - $dataanswer->alternatives)) - { - $result->error = "Could not insert multianswer alternatives! (questionid=$question->id)"; - return $result; - } - $DB->insert_record("quiz_multianswers", $multianswer); - } - } - break; - - case LESSON_RANDOM: - break; - - case LESSON_DESCRIPTION: - break; - - default: - $result->error = "Unsupported question type ($question->qtype)!"; - return $result; - break; - } - return true; -} - -/** - * Determins if a jumpto value is correct or not. - * - * returns true if jumpto page is (logically) after the pageid page or - * if the jumpto value is a special value. Returns false in all other cases. - * - * @param int $pageid Id of the page from which you are jumping from. - * @param int $jumpto The jumpto number. - * @return boolean True or false after a series of tests. - **/ -function lesson_iscorrect($pageid, $jumpto) { - global $DB; - - // first test the special values - if (!$jumpto) { - // same page - return false; - } elseif ($jumpto == LESSON_NEXTPAGE) { - return true; - } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) { - return true; - } elseif ($jumpto == LESSON_RANDOMPAGE) { - return true; - } elseif ($jumpto == LESSON_CLUSTERJUMP) { - return true; - } elseif ($jumpto == LESSON_EOL) { - return true; - } - // we have to run through the pages from pageid looking for jumpid - if ($lessonid = $DB->get_field('lesson_pages', 'lessonid', array('id' => $pageid))) { - if ($pages = $DB->get_records('lesson_pages', array('lessonid' => $lessonid), '', 'id, nextpageid')) { - $apageid = $pages[$pageid]->nextpageid; - while ($apageid != 0) { - if ($jumpto == $apageid) { - return true; - } - $apageid = $pages[$apageid]->nextpageid; - } - } - } - return false; -} - -/** - * Checks to see if a page is a branch table or is - * a page that is enclosed by a branch table and an end of branch or end of lesson. - * May call this function: {@link lesson_is_page_in_branch()} - * - * @param int $lesson Id of the lesson to which the page belongs. - * @param int $pageid Id of the page. - * @return boolean True or false. - **/ -function lesson_display_branch_jumps($lessonid, $pageid) { - global $DB; - - if($pageid == 0) { - // first page - return false; - } - // get all of the lesson pages - $params = array ("lessonid" => $lessonid); - if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) { - // adding first page - return false; - } - - if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) { - return true; - } - - return lesson_is_page_in_branch($lessonpages, $pageid); -} - -/** - * Checks to see if a page is a cluster page or is - * a page that is enclosed by a cluster page and an end of cluster or end of lesson - * May call this function: {@link lesson_is_page_in_cluster()} - * - * @param int $lesson Id of the lesson to which the page belongs. - * @param int $pageid Id of the page. - * @return boolean True or false. - **/ -function lesson_display_cluster_jump($lesson, $pageid) { - global $DB; - - if($pageid == 0) { - // first page - return false; - } - // get all of the lesson pages - $params = array ("lessonid" => $lesson); - if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) { - // adding first page - return false; - } - - if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) { - return true; - } - - return lesson_is_page_in_cluster($lessonpages, $pageid); - -} - /** * Checks to see if a LESSON_CLUSTERJUMP or * a LESSON_UNSEENBRANCHPAGE is used in a lesson. @@ -1028,7 +71,7 @@ function lesson_display_teacher_warning($lesson) { global $DB; // get all of the lesson answers - $params = array ("lessonid" => $lesson); + $params = array ("lessonid" => $lesson->id); if (!$lessonanswers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid", $params)) { // no answers, then not useing cluster or unseen return false; @@ -1044,148 +87,12 @@ function lesson_display_teacher_warning($lesson) { return false; } - -/** - * Interprets LESSON_CLUSTERJUMP jumpto value. - * - * This will select a page randomly - * and the page selected will be inbetween a cluster page and end of cluter or end of lesson - * and the page selected will be a page that has not been viewed already - * and if any pages are within a branch table or end of branch then only 1 page within - * the branch table or end of branch will be randomly selected (sub clustering). - * - * @param int $lessonid Id of the lesson. - * @param int $userid Id of the user. - * @param int $pageid Id of the current page from which we are jumping from. - * @return int The id of the next page. - **/ -function lesson_cluster_jump($lessonid, $userid, $pageid) { - global $DB; - - // get the number of retakes - if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lessonid, "userid"=>$userid))) { - $retakes = 0; - } - - // get all the lesson_attempts aka what the user has seen - $params = array ("lessonid" => $lessonid, "userid" => $userid, "retry" => $retakes); - if ($seen = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen DESC")) { - foreach ($seen as $value) { // load it into an array that I can more easily use - $seenpages[$value->pageid] = $value->pageid; - } - } else { - $seenpages = array(); - } - - // get the lesson pages - if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) { - print_error('cannotfindrecords', 'lesson'); - } - // find the start of the cluster - while ($pageid != 0) { // this condition should not be satisfied... should be a cluster page - if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) { - break; - } - $pageid = $lessonpages[$pageid]->prevpageid; - } - - $pageid = $lessonpages[$pageid]->nextpageid; // move down from the cluster page - - $clusterpages = array(); - while (true) { // now load all the pages into the cluster that are not already inside of a branch table. - if ($lessonpages[$pageid]->qtype == LESSON_ENDOFCLUSTER) { - // store the endofcluster page's jump - $exitjump = $DB->get_field("lesson_answers", "jumpto", array("pageid" => $pageid, "lessonid" => $lessonid)); - if ($exitjump == LESSON_NEXTPAGE) { - $exitjump = $lessonpages[$pageid]->nextpageid; - } - if ($exitjump == 0) { - $exitjump = LESSON_EOL; - } - break; - } elseif (!lesson_is_page_in_branch($lessonpages, $pageid) && $lessonpages[$pageid]->qtype != LESSON_ENDOFBRANCH) { - // load page into array when it is not in a branch table and when it is not an endofbranch - $clusterpages[] = $lessonpages[$pageid]; - } - if ($lessonpages[$pageid]->nextpageid == 0) { - // shouldn't ever get here... should be using endofcluster - $exitjump = LESSON_EOL; - break; - } else { - $pageid = $lessonpages[$pageid]->nextpageid; - } - } - - // filter out the ones we have seen - $unseen = array(); - foreach ($clusterpages as $clusterpage) { - if ($clusterpage->qtype == LESSON_BRANCHTABLE) { // if branchtable, check to see if any pages inside have been viewed - $branchpages = lesson_pages_in_branch($lessonpages, $clusterpage->id); // get the pages in the branchtable - $flag = true; - foreach ($branchpages as $branchpage) { - if (array_key_exists($branchpage->id, $seenpages)) { // check if any of the pages have been viewed - $flag = false; - } - } - if ($flag && count($branchpages) > 0) { - // add branch table - $unseen[] = $clusterpage; - } - } else { - // add any other type of page that has not already been viewed - if (!array_key_exists($clusterpage->id, $seenpages)) { - $unseen[] = $clusterpage; - } - } - } - - if (count($unseen) > 0) { // it does not contain elements, then use exitjump, otherwise find out next page/branch - $nextpage = $unseen[rand(0, count($unseen)-1)]; - } else { - return $exitjump; // seen all there is to see, leave the cluster - } - - if ($nextpage->qtype == LESSON_BRANCHTABLE) { // if branch table, then pick a random page inside of it - $branchpages = lesson_pages_in_branch($lessonpages, $nextpage->id); - return $branchpages[rand(0, count($branchpages)-1)]->id; - } else { // otherwise, return the page's id - return $nextpage->id; - } -} - -/** - * Returns pages that are within a branch table and another branch table, end of branch or end of lesson - * - * @param array $lessonpages An array of lesson page objects. - * @param int $branchid The id of the branch table that we would like the containing pages for. - * @return array An array of lesson page objects. - **/ -function lesson_pages_in_branch($lessonpages, $branchid) { - $pageid = $lessonpages[$branchid]->nextpageid; // move to the first page after the branch table - $pagesinbranch = array(); - - while (true) { - if ($pageid == 0) { // EOL - break; - } elseif ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) { - break; - } elseif ($lessonpages[$pageid]->qtype == LESSON_ENDOFBRANCH) { - break; - } - $pagesinbranch[] = $lessonpages[$pageid]; - $pageid = $lessonpages[$pageid]->nextpageid; - } - - return $pagesinbranch; -} - /** * Interprets the LESSON_UNSEENBRANCHPAGE jump. * * will return the pageid of a random unseen page that is within a branch * - * @see lesson_pages_in_branch() - * @param int $lesson Id of the lesson. + * @param lesson $lesson * @param int $userid Id of the user. * @param int $pageid Id of the page from which we are jumping. * @return int Id of the next page. @@ -1194,13 +101,12 @@ function lesson_unseen_question_jump($lesson, $user, $pageid) { global $DB; // get the number of retakes - if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson, "userid"=>$user))) { + if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$user))) { $retakes = 0; } // get all the lesson_attempts aka what the user has seen - $params = array ("lessonid" => $lesson, "userid" => $user, "retry" => $retakes); - if ($viewedpages = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen DESC")) { + if ($viewedpages = $DB->get_records("lesson_attempts", array("lessonid"=>$lesson->id, "userid"=>$user, "retry"=>$retakes), "timeseen DESC")) { foreach($viewedpages as $viewed) { $seenpages[] = $viewed->pageid; } @@ -1209,9 +115,7 @@ function lesson_unseen_question_jump($lesson, $user, $pageid) { } // get the lesson pages - if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) { - print_error('cannotfindpages', 'lesson'); - } + $lessonpages = $lesson->load_all_pages(); if ($pageid == LESSON_UNSEENBRANCHPAGE) { // this only happens when a student leaves in the middle of an unseen question within a branch series $pageid = $seenpages[0]; // just change the pageid to the last page viewed inside the branch table @@ -1219,13 +123,13 @@ function lesson_unseen_question_jump($lesson, $user, $pageid) { // go up the pages till branch table while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page - if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) { + if ($lessonpages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE) { break; } $pageid = $lessonpages[$pageid]->prevpageid; } - $pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid); + $pagesinbranch = $this->get_sub_pages_of($pageid, array(LESSON_PAGE_BRANCHTABLE, LESSON_PAGE_ENDOFBRANCH)); // this foreach loop stores all the pages that are within the branch table but are not in the $seenpages array $unseen = array(); @@ -1256,27 +160,25 @@ function lesson_unseen_question_jump($lesson, $user, $pageid) { /** * Handles the unseen branch table jump. * - * @param int $lessonid Lesson id. + * @param lesson $lesson * @param int $userid User id. * @return int Will return the page id of a branch table or end of lesson **/ -function lesson_unseen_branch_jump($lessonid, $userid) { +function lesson_unseen_branch_jump($lesson, $userid) { global $DB; - if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lessonid, "userid"=>$userid))) { + if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$userid))) { $retakes = 0; } - $params = array ("lessonid" => $lessonid, "userid" => $userid, "retry" => $retakes); + $params = array ("lessonid" => $lesson->id, "userid" => $userid, "retry" => $retakes); if (!$seenbranches = $DB->get_records_select("lesson_branch", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen DESC")) { print_error('cannotfindrecords', 'lesson'); } // get the lesson pages - if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) { - print_error('cannotfindpages', 'lesson'); - } + $lessonpages = $lesson->load_all_pages(); // this loads all the viewed branch tables into $seen untill it finds the branch table with the flag // which is the branch table that starts the unseenbranch function @@ -1293,7 +195,7 @@ function lesson_unseen_branch_jump($lessonid, $userid) { // that follow the flagged branch table $pageid = $lessonpages[$start]->nextpageid; // move down from the flagged branch table while ($pageid != 0) { // grab all of the branch table till eol - if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) { + if ($lessonpages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE) { $branchtables[] = $lessonpages[$pageid]->id; } $pageid = $lessonpages[$pageid]->nextpageid; @@ -1315,15 +217,15 @@ function lesson_unseen_branch_jump($lessonid, $userid) { /** * Handles the random jump between a branch table and end of branch or end of lesson (LESSON_RANDOMPAGE). * - * @param int $lessonid Lesson id. + * @param lesson $lesson * @param int $pageid The id of the page that we are jumping from (?) * @return int The pageid of a random page that is within a branch table **/ -function lesson_random_question_jump($lessonid, $pageid) { +function lesson_random_question_jump($lesson, $pageid) { global $DB; // get the lesson pages - $params = array ("lessonid" => $lessonid); + $params = array ("lessonid" => $lesson->id); if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) { print_error('cannotfindpages', 'lesson'); } @@ -1331,14 +233,14 @@ function lesson_random_question_jump($lessonid, $pageid) { // go up the pages till branch table while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page - if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) { + if ($lessonpages[$pageid]->qtype == LESSON_PAGE_BRANCHTABLE) { break; } $pageid = $lessonpages[$pageid]->prevpageid; } // get the pages within the branch - $pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid); + $pagesinbranch = $this->get_sub_pages_of($pageid, array(LESSON_PAGE_BRANCHTABLE, LESSON_PAGE_ENDOFBRANCH)); if(count($pagesinbranch) == 0) { // there are no pages inside the branch, so return the next page @@ -1348,63 +250,6 @@ function lesson_random_question_jump($lessonid, $pageid) { } } -/** - * Check to see if a page is below a branch table (logically). - * - * Will return true if a branch table is found logically above the page. - * Will return false if an end of branch, cluster or the beginning - * of the lesson is found before a branch table. - * - * @param array $pages An array of lesson page objects. - * @param int $pageid Id of the page for testing. - * @return boolean - */ -function lesson_is_page_in_branch($pages, $pageid) { - $pageid = $pages[$pageid]->prevpageid; // move up one - - // go up the pages till branch table - while (true) { - if ($pageid == 0) { // ran into the beginning of the lesson - return false; - } elseif ($pages[$pageid]->qtype == LESSON_ENDOFBRANCH) { // ran into the end of another branch table - return false; - } elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // do not look beyond a cluster - return false; - } elseif ($pages[$pageid]->qtype == LESSON_BRANCHTABLE) { // hit a branch table - return true; - } - $pageid = $pages[$pageid]->prevpageid; - } - -} - -/** - * Check to see if a page is below a cluster page (logically). - * - * Will return true if a cluster is found logically above the page. - * Will return false if an end of cluster or the beginning - * of the lesson is found before a cluster page. - * - * @param array $pages An array of lesson page objects. - * @param int $pageid Id of the page for testing. - * @return boolean - */ -function lesson_is_page_in_cluster($pages, $pageid) { - $pageid = $pages[$pageid]->prevpageid; // move up one - - // go up the pages till branch table - while (true) { - if ($pageid == 0) { // ran into the beginning of the lesson - return false; - } elseif ($pages[$pageid]->qtype == LESSON_ENDOFCLUSTER) { // ran into the end of another branch table - return false; - } elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // hit a branch table - return true; - } - $pageid = $pages[$pageid]->prevpageid; - } -} - /** * Calculates a user's grade for a lesson. * @@ -1453,24 +298,24 @@ function lesson_grade($lesson, $ntries, $userid = 0) { // get only the pages and their answers that the user answered list($usql, $parameters) = $DB->get_in_or_equal(array_keys($attemptset)); - $parameters["lessonid"] = $lesson->id; - $pages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid AND id $usql", $parameters); - $answers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid AND pageid $usql", $parameters); + array_unshift($parameters, $lesson->id); + $pages = $DB->get_records_select("lesson_pages", "lessonid = ? AND id $usql", $parameters); + $answers = $DB->get_records_select("lesson_answers", "lessonid = ? AND pageid $usql", $parameters); // Number of pages answered $nquestions = count($pages); foreach ($attemptset as $attempts) { + $page = lesson_page::load($pages[end($attempts)->pageid], $lesson); if ($lesson->custom) { $attempt = end($attempts); // If essay question, handle it, otherwise add to score - if ($pages[$attempt->pageid]->qtype == LESSON_ESSAY) { - $essayinfo = unserialize($attempt->useranswer); - $earned += $essayinfo->score; + if ($page->requires_manual_grading()) { + $earned += $page->earned_score($answers, $attempt); $nmanual++; $manualpoints += $answers[$attempt->answerid]->score; } else if (!empty($attempt->answerid)) { - $earned += $answers[$attempt->answerid]->score; + $earned += $page->earned_score($answers, $attempt); } } else { foreach ($attempts as $attempt) { @@ -1478,7 +323,7 @@ function lesson_grade($lesson, $ntries, $userid = 0) { } $attempt = end($attempts); // doesn't matter which one // If essay question, increase numbers - if ($pages[$attempt->pageid]->qtype == LESSON_ESSAY) { + if ($page->requires_manual_grading()) { $nmanual++; $manualpoints++; } @@ -1526,180 +371,6 @@ function lesson_grade($lesson, $ntries, $userid = 0) { return $gradeinfo; } -/** - * Prints the on going message to the user. - * - * With custom grading On, displays points - * earned out of total points possible thus far. - * With custom grading Off, displays number of correct - * answers out of total attempted. - * - * @param object $lesson The lesson that the user is taking. - * @return void - **/ -function lesson_print_ongoing_score($lesson) { - global $USER, $DB, $OUTPUT; - - $cm = get_coursemodule_from_instance('lesson', $lesson->id); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - if (has_capability('mod/lesson:manage', $context)) { - echo "

      ".get_string('teacherongoingwarning', 'lesson').'

      '; - } else { - $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - if (isset($USER->modattempts[$lesson->id])) { - $ntries--; - } - $gradeinfo = lesson_grade($lesson, $ntries); - - $a = new stdClass; - if ($lesson->custom) { - $a->score = $gradeinfo->earned; - $a->currenthigh = $gradeinfo->total; - echo $OUTPUT->box(get_string("ongoingcustom", "lesson", $a), "generalbox boxaligncenter"); - } else { - $a->correct = $gradeinfo->earned; - $a->viewed = $gradeinfo->attempts; - echo $OUTPUT->box(get_string("ongoingnormal", "lesson", $a), "generalbox boxaligncenter"); - } - } -} - -/** - * Prints tabs for the editing and adding pages. Each tab is a question type. - * - * @param array $qtypes The question types array (may not need to pass this because it is defined in this file) - * @param string $selected Current selected tab - * @param string $link The base href value of the link for the tab - * @param string $onclick Javascript for the tab link - * @return void - */ -function lesson_qtype_menu($qtypes, $selected="", $link="", $onclick="") { - $tabs = array(); - $tabrows = array(); - - foreach ($qtypes as $qtype => $qtypename) { - $tabrows[] = new tabobject($qtype, "$link&qtype=$qtype\" onclick=\"$onclick", $qtypename); - } - $tabs[] = $tabrows; - print_tabs($tabs, $selected); - echo " \n"; - -} - -/** - * Prints out a Progress Bar which depicts a user's progress within a lesson. - * - * Currently works best with a linear lesson. Clusters are counted as a single page. - * Also, only viewed branch tables and questions that have been answered correctly count - * toward lesson completion (or progress). Only Students can see the Progress bar as well. - * - * @param object $lesson The lesson that the user is currently taking. - * @param object $course The course that the to which the lesson belongs. - * @return boolean The return is not significant as of yet. Will return true/false. - **/ -function lesson_print_progress_bar($lesson, $course) { - global $CFG, $USER, $DB, $OUTPUT; - - $cm = get_coursemodule_from_instance('lesson', $lesson->id); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - - // lesson setting to turn progress bar on or off - if (!$lesson->progressbar) { - return false; - } - - // catch teachers - if (has_capability('mod/lesson:manage', $context)) { - echo $OUTPUT->notification(get_string('progressbarteacherwarning2', 'lesson')); - return false; - } - if (!isset($USER->modattempts[$lesson->id])) { - // all of the lesson pages - if (!$pages = $DB->get_records('lesson_pages', array('lessonid' => $lesson->id))) { - return false; - } else { - foreach ($pages as $page) { - if ($page->prevpageid == 0) { - $pageid = $page->id; // find the first page id - break; - } - } - } - - // current attempt number - if (!$ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id))) { - $ntries = 0; // may not be necessary - } - - $viewedpageids = array(); - - // collect all of the correctly answered questions - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries); - if ($viewedpages = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry AND correct = 1", $params, 'timeseen DESC', 'pageid, id')) { - $viewedpageids = array_keys($viewedpages); - } - // collect all of the branch tables viewed - if ($viewedbranches = $DB->get_records_select("lesson_branch", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, 'timeseen DESC', 'pageid, id')) { - $viewedpageids = array_merge($viewedpageids, array_keys($viewedbranches)); - } - - // Filter out the following pages: - // End of Cluster - // End of Branch - // Pages found inside of Clusters - // Do not filter out Cluster Page(s) because we count a cluster as one. - // By keeping the cluster page, we get our 1 - $validpages = array(); - while ($pageid != 0) { - if ($pages[$pageid]->qtype == LESSON_CLUSTER) { - $clusterpageid = $pageid; // copy it - $validpages[$clusterpageid] = 1; // add the cluster page as a valid page - $pageid = $pages[$pageid]->nextpageid; // get next page - - // now, remove all necessary viewed paged ids from the viewedpageids array. - while ($pages[$pageid]->qtype != LESSON_ENDOFCLUSTER and $pageid != 0) { - if (in_array($pageid, $viewedpageids)) { - unset($viewedpageids[array_search($pageid, $viewedpageids)]); // remove it - // since the user did see one page in the cluster, add the cluster pageid to the viewedpageids - if (!in_array($clusterpageid, $viewedpageids)) { - $viewedpageids[] = $clusterpageid; - } - } - $pageid = $pages[$pageid]->nextpageid; - } - } elseif ($pages[$pageid]->qtype == LESSON_ENDOFCLUSTER or $pages[$pageid]->qtype == LESSON_ENDOFBRANCH) { - // dont count these, just go to next - $pageid = $pages[$pageid]->nextpageid; - } else { - // a counted page - $validpages[$pageid] = 1; - $pageid = $pages[$pageid]->nextpageid; - } - } - - // progress calculation as a percent - $progress = round(count($viewedpageids)/count($validpages), 2) * 100; - } else { - $progress = 100; - } - - // print out the Progress Bar. Attempted to put as much as possible in the style sheets. - echo '
      '; - echo ''; - if ($progress != 0) { // some browsers do not repsect the 0 width. - echo ''; - } - echo ''; - echo '
      '; - echo ''; - echo '
      '; - echo '
      '; - echo '
      '; - - return true; -} - /** * Determines if a user can view the left menu. The determining factor * is whether a user has a grade greater than or equal to the lesson setting @@ -1765,18 +436,24 @@ function lesson_add_pretend_blocks($page, $cm, $lesson, $timer = null) { **/ function lesson_mediafile_block_contents($cmid, $lesson) { global $OUTPUT; - if (empty($lesson->mediafile)) { + if (empty($lesson->mediafile) && empty($lesson->mediafileid)) { return null; } - $url = '/mod/lesson/mediafile.php?id='.$cmid; - $options = 'menubar=0,location=0,left=5,top=5,scrollbars,resizable,width='. $lesson->mediawidth .',height='. $lesson->mediaheight; - $name = 'lessonmediafile'; + $options = array(); + $options['menubar'] = 0; + $options['location'] = 0; + $options['left'] = 5; + $options['top'] = 5; + $options['scrollbars'] = 1; + $options['resizable'] = 1; + $options['width'] = $lesson->mediawidth; + $options['height'] = $lesson->mediaheight; - $link = html_link::make($url, get_string('mediafilepopup', 'lesson')); - $link->add_action(new popup_action('click', $link->url, $name, $options)); + $link = html_link::make('/mod/lesson/mediafile.php?id='.$cmid, get_string('mediafilepopup', 'lesson')); + $link->add_action(new popup_action('click', $link->url, 'lessonmediafile', $options)); $link->title = get_string('mediafilepopup', 'lesson'); - $content .= $OUTPUT->link($link); + $content = $OUTPUT->link($link); $content .= $OUTPUT->help_icon(moodle_help_icon::make("mediafilestudent", get_string("mediafile", "lesson"), "lesson")); @@ -1805,7 +482,7 @@ function lesson_clock_block_contents($cmid, $lesson, $timer, $page) { } $content = '
      '; - $content .= lesson_print_time_remaining($timer->starttime, $lesson->maxtime, true)."\n"; + $content .= $lesson->time_remaining($timer->starttime); $content .= '
      '; $clocksettings = array('starttime'=>$timer->starttime, 'servertime'=>time(),'testlength'=>($lesson->maxtime * 60)); @@ -1826,7 +503,7 @@ function lesson_clock_block_contents($cmid, $lesson, $timer, $page) { * print the menu in a block * * @param int $cmid Course Module ID for this lesson - * @param object $lesson Full lesson record object + * @param lesson $lesson Full lesson record object * @return void **/ function lesson_menu_block_contents($cmid, $lesson) { @@ -1836,9 +513,13 @@ function lesson_menu_block_contents($cmid, $lesson) { return null; } - $pageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0)); - $params = array ("lessonid" => $lesson->id); - $pages = $DB->get_records_select('lesson_pages', "lessonid = :lessonid", $params); + $pages = $lesson->load_all_pages(); + foreach ($pages as $page) { + if ((int)$page->prevpageid === 0) { + $pageid = $page->id; + break; + } + } $currentpageid = optional_param('pageid', $pageid, PARAM_INT); if (!$pageid || !$pages) { @@ -1851,7 +532,7 @@ function lesson_menu_block_contents($cmid, $lesson) { $page = $pages[$pageid]; // Only process branch tables with display turned on - if ($page->qtype == LESSON_BRANCHTABLE and $page->display) { + if ($page->displayinmenublock && $page->display) { if ($page->id == $currentpageid) { $content .= '
    • '.format_string($page->title,true)."
    • \n"; } else { @@ -1869,4 +550,4 @@ function lesson_menu_block_contents($cmid, $lesson) { $bc->content = $content; return $bc; -} +} \ No newline at end of file diff --git a/mod/lesson/mediafile.php b/mod/lesson/mediafile.php index f1ba378551..8a1fb17ae2 100644 --- a/mod/lesson/mediafile.php +++ b/mod/lesson/mediafile.php @@ -1,5 +1,20 @@ . + /** * This file plays the mediafile set in lesson settings. * @@ -8,211 +23,61 @@ * If there is a way to use the resource class instead of this code, please change to do so * * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later **/ - require_once('../../config.php'); - require_once($CFG->libdir.'/filelib.php'); +require_once('../../config.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once($CFG->libdir.'/filelib.php'); +require_once($CFG->libdir.'/resourcelib.php'); - $id = required_param('id', PARAM_INT); // Course Module ID - $printclose = optional_param('printclose', 0, PARAM_INT); +$id = required_param('id', PARAM_INT); // Course Module ID +$printclose = optional_param('printclose', 0, PARAM_INT); - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/mediafile.php', array('id'=>$id)); - if ($printclose !== '') { - $url->param('printclose', $printclose); - } - $PAGE->set_url($url); +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/mediafile.php', array('id'=>$id)); +if ($printclose !== '') { + $url->param('printclose', $printclose); +} +$PAGE->set_url($url); - if (! $cm = get_coursemodule_from_id('lesson', $id)) { - print_error('invalidcoursemodule'); - } +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); - if (! $course = $DB->get_record('course', array('id' => $cm->course))) { - print_error('coursemisconf'); - } +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); - if (! $lesson = $DB->get_record('lesson', array('id' => $cm->instance))) { - print_error('invalidcoursemodule'); - } +// Get the mimetype +$mimetype = mimeinfo("type", $lesson->mediafile); - require_login($course->id, false, $cm); - - // Get the mimetype - $mimetype = mimeinfo("type", $lesson->mediafile); - - if (!is_url($lesson->mediafile) and !in_array($mimetype, array('text/plain', 'text/html'))) { +if ($printclose) { // this is for framesets + if ($lesson->mediaclose) { $PAGE->set_title($course->shortname); - echo $OUTPUT->header(); + echo $lessonoutput->header($lesson); + echo $OUTPUT->box('
      ', 'lessonmediafilecontrol'); + echo $lessonoutput->footer(); } + exit(); +} - if ($printclose) { // this is for framesets - if ($lesson->mediaclose) { - $PAGE->set_title($course->shortname); - echo $OUTPUT->header(); - echo '
      -
      -
      - -
      -
      -
      '; - echo $OUTPUT->footer(); - } - exit(); - } - - if (is_url($lesson->mediafile)) { - $fullurl = $lesson->mediafile; - } else { - $fullurl = get_file_url($course->id .'/'. $lesson->mediafile); - } - - // find the correct type and print it out - if ($mimetype == "audio/mp3") { // It's an MP3 audio file - - if (!empty($THEME->resource_mp3player_colors)) { - $c = $THEME->resource_mp3player_colors; // You can set this up in your theme/xxx/config.php - } else { - $c = 'bgColour=000000&btnColour=ffffff&btnBorderColour=cccccc&iconColour=000000&'. - 'iconOverColour=00cc00&trackColour=cccccc&handleColour=ffffff&loaderColour=ffffff&'. - 'font=Arial&fontColour=3333FF&buffer=10&waitForPlay=no&autoPlay=yes'; - } - $c .= '&volText='.get_string('vol', 'resource').'&panText='.get_string('pan','resource'); - $c = htmlentities($c); - echo '
      '; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
      '; - - } else if (substr($mimetype, 0, 10) == "video/x-ms") { // It's a Media Player file - - echo "

      "; - echo ''; - echo ""; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo "\n'; - echo ''; - echo ''; - echo "

      "; - - } else if ($mimetype == "video/quicktime") { // It's a Quicktime file - - echo "

      "; - echo ''; - echo ""; - echo ''; - echo ''; - echo ''; - echo ''; - echo "\n'; - echo ''; - echo ''; - echo "

      "; +$mediafilehtml = lesson_get_media_html($lesson, $context); - //} else if ($mimetype == "application/x-shockwave-flash") { // It's a flash file - - // print_error('noflash'); - - } else if ($mimetype == "audio/x-pn-realaudio") { // It's a realmedia file - - echo ''; - echo ""; - echo ''; // not sure what the console param should equal - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - - } else if (is_url($lesson->mediafile) or $mimetype == 'text/html' or $mimetype == 'text/plain') { - // might be dangerous to handle all of these in the same fasion. It is being set by a teacher though. - echo "\n"; - echo "\n"; - echo ''; - echo ''; - echo "{$course->shortname}\n"; - if ($lesson->mediaclose) { - echo ""; - echo ""; - echo "id&printclose=1\" />"; - echo ""; - } else { - echo ""; - echo ""; - echo ""; - } - echo ''; - exit(); - - } else if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // Image - - echo "

      "; - echo ''; - echo "

      "; - - } else { // Default - - // Get the file name - $file = pathinfo($lesson->mediafile); - $filename = basename($file['basename'], '.'.$file['extension']); - - echo "

      "; - echo $OUTPUT->notification(get_string('clicktodownload', 'lesson')); - echo "".format_string($filename).''; - echo "

      "; - - } - - function is_url($test_url) { - // the following is barrowed from resource code. Thanks! - if (strpos($test_url, '://')) { // eg http:// https:// ftp:// etc - return true; - } - if (strpos($test_url, '/') === 0) { // Starts with slash - return true; - } - return false; - } - - if ($lesson->mediaclose) { - echo '
      '; - echo $OUTPUT->close_window_button(); - echo '
      '; - } +$PAGE->set_title($course->shortname); +echo $lessonoutput->header($lesson); +// print the embedded media html code +echo $OUTPUT->box($mediafilehtml); - echo $OUTPUT->footer(); +if ($lesson->mediaclose) { + echo '
      '; + echo $OUTPUT->close_window_button(); + echo '
      '; +} +echo $lessonoutput->footer(); \ No newline at end of file diff --git a/mod/lesson/mod_form.php b/mod/lesson/mod_form.php index e61dccde13..af7212911a 100644 --- a/mod/lesson/mod_form.php +++ b/mod/lesson/mod_form.php @@ -1,25 +1,84 @@ . + /** * Form to define a new instance of lesson or edit an instance. * It is used from /course/modedit.php. * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ require_once($CFG->dirroot.'/course/moodleform_mod.php'); -require_once('locallib.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); class mod_lesson_mod_form extends moodleform_mod { + protected $course = null; + + public function mod_lesson_mod_form($current, $section, $cm, $course) { + $this->course = $course; + parent::moodleform_mod($current, $section, $cm, $course); + } + function definition() { - global $CFG, $LESSON_NEXTPAGE_ACTION, $COURSE, $DB; + global $CFG, $COURSE, $DB; - $mform =& $this->_form; + $mform = $this->_form; //------------------------------------------------------------------------------- $mform->addElement('header', 'general', get_string('general', 'form')); + /** Legacy slideshow width element to maintain backwards compatibility */ + $mform->addElement('hidden', 'width'); + $mform->setType('width', PARAM_INT); + $mform->setDefault('width', $CFG->lesson_slideshowwidth); + + /** Legacy slideshow height element to maintain backwards compatibility */ + $mform->addElement('hidden', 'height'); + $mform->setType('height', PARAM_INT); + $mform->setDefault('height', $CFG->lesson_slideshowheight); + + /** Legacy slideshow background color element to maintain backwards compatibility */ + $mform->addElement('hidden', 'bgcolor'); + $mform->setType('bgcolor', PARAM_TEXT); + $mform->setDefault('bgcolor', $CFG->lesson_slideshowbgcolor); + + /** Legacy media popup width element to maintain backwards compatibility */ + $mform->addElement('hidden', 'mediawidth'); + $mform->setType('mediawidth', PARAM_INT); + $mform->setDefault('mediawidth', $CFG->lesson_mediawidth); + + /** Legacy media popup height element to maintain backwards compatibility */ + $mform->addElement('hidden', 'mediaheight'); + $mform->setType('mediaheight', PARAM_INT); + $mform->setDefault('mediaheight', $CFG->lesson_mediaheight); + + /** Legacy media popup close button element to maintain backwards compatibility */ + $mform->addElement('hidden', 'mediaclose'); + $mform->setType('mediaclose', PARAM_BOOL); + $mform->setDefault('mediaclose', $CFG->lesson_mediaclose); + + /** Legacy maximum highscores element to maintain backwards compatibility */ + $mform->addElement('hidden', 'maxhighscores'); + $mform->setType('maxhighscores', PARAM_INT); + $mform->setDefault('maxhighscores', $CFG->lesson_maxhighscores); + $mform->addElement('text', 'name', get_string('name'), array('size'=>'64')); if (!empty($CFG->formatstringstriptags)) { $mform->setType('name', PARAM_TEXT); @@ -50,12 +109,32 @@ class mod_lesson_mod_form extends moodleform_mod { for ($i=20; $i>1; $i--) { $numbers[$i] = $i; } + + $mform->addElement('date_time_selector', 'available', get_string('available', 'lesson'), array('optional'=>true)); + $mform->setDefault('available', 0); + + $mform->addElement('date_time_selector', 'deadline', get_string('deadline', 'lesson'), array('optional'=>true)); + $mform->setDefault('deadline', 0); + $mform->addElement('select', 'maxanswers', get_string('maximumnumberofanswersbranches', 'lesson'), $numbers); - $mform->setDefault('maxanswers', 4); + $mform->setDefault('maxanswers', $CFG->lesson_maxanswers); + $mform->setType('maxanswers', PARAM_INT); $mform->setHelpButton('maxanswers', array('maxanswers', get_string('maximumnumberofanswersbranches', 'lesson'), 'lesson')); + $mform->addElement('selectyesno', 'usepassword', get_string('usepassword', 'lesson')); + $mform->setHelpButton('usepassword', array('usepassword', get_string('usepassword', 'lesson'), 'lesson')); + $mform->setDefault('usepassword', 0); + $mform->setAdvanced('usepassword'); + + $mform->addElement('passwordunmask', 'password', get_string('password', 'lesson')); + $mform->setHelpButton('password', array('password', get_string('password', 'lesson'), 'lesson')); + $mform->setDefault('password', ''); + $mform->setType('password', PARAM_RAW); + $mform->setAdvanced('password'); + $mform->disabledIf('password', 'usepassword', 'eq', 0); + //------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('gradeoptions', 'lesson')); + $mform->addElement('header', 'gradeoptions', get_string('gradeoptions', 'lesson')); $mform->addElement('selectyesno', 'practice', get_string('practice', 'lesson')); $mform->setHelpButton('practice', array('practice', get_string('practice', 'lesson'), 'lesson')); @@ -72,6 +151,7 @@ class mod_lesson_mod_form extends moodleform_mod { $mform->addElement('select', 'grade', get_string('maximumgrade'), $grades); $mform->setDefault('grade', 0); $mform->setHelpButton('grade', array('grade', get_string('maximumgrade'), 'lesson')); + $mform->disabledIf('grade', 'practice', 'eq', '1'); $mform->addElement('selectyesno', 'retake', get_string('retakesallowed', 'lesson')); $mform->setHelpButton('retake', array('retake', get_string('retakesallowed', 'lesson'), 'lesson')); @@ -83,13 +163,14 @@ class mod_lesson_mod_form extends moodleform_mod { $mform->addElement('select', 'usemaxgrade', get_string('handlingofretakes', 'lesson'), $options); $mform->setHelpButton('usemaxgrade', array('handlingofretakes', get_string('handlingofretakes', 'lesson'), 'lesson')); $mform->setDefault('usemaxgrade', 0); + $mform->disabledIf('usemaxgrade', 'retake', 'eq', '0'); $mform->addElement('selectyesno', 'ongoing', get_string('ongoing', 'lesson')); $mform->setHelpButton('ongoing', array('ongoing', get_string('ongoing', 'lesson'), 'lesson')); $mform->setDefault('ongoing', 0); //------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('flowcontrol', 'lesson')); + $mform->addElement('header', 'flowcontrol', get_string('flowcontrol', 'lesson')); $mform->addElement('selectyesno', 'modattempts', get_string('modattempts', 'lesson')); $mform->setHelpButton('modattempts', array('modattempts', get_string('modattempts', 'lesson'), 'lesson')); @@ -107,14 +188,36 @@ class mod_lesson_mod_form extends moodleform_mod { $mform->setHelpButton('maxattempts', array('maxattempts', get_string('maximumnumberofattempts', 'lesson'), 'lesson')); $mform->setDefault('maxattempts', 1); - $mform->addElement('select', 'nextpagedefault', get_string('actionaftercorrectanswer', 'lesson'), $LESSON_NEXTPAGE_ACTION); + $defaultnextpages = array(); + $defaultnextpages[0] = get_string("normal", "lesson"); + $defaultnextpages[LESSON_UNSEENPAGE] = get_string("showanunseenpage", "lesson"); + $defaultnextpages[LESSON_UNANSWEREDPAGE] = get_string("showanunansweredpage", "lesson"); + $mform->addElement('select', 'nextpagedefault', get_string('actionaftercorrectanswer', 'lesson'), $defaultnextpages); $mform->setHelpButton('nextpagedefault', array('nextpageaction', get_string('actionaftercorrectanswer', 'lesson'), 'lesson')); - $mform->setDefault('nextpagedefault', 0); + $mform->setDefault('nextpagedefault', $CFG->lesson_defaultnextpage); + $mform->setAdvanced('nextpagedefault'); $mform->addElement('selectyesno', 'feedback', get_string('displaydefaultfeedback', 'lesson')); $mform->setHelpButton('feedback', array('feedback', get_string('displaydefaultfeedback', 'lesson'), 'lesson')); $mform->setDefault('feedback', 0); + $mform->addElement('selectyesno', 'progressbar', get_string('progressbar', 'lesson')); + $mform->setHelpButton('progressbar', array('progressbar', get_string('progressbar', 'lesson'), 'lesson')); + $mform->setDefault('progressbar', 0); + + $mform->addElement('selectyesno', 'displayleft', get_string('displayleftmenu', 'lesson')); + $mform->setHelpButton('displayleft', array('displayleft', get_string('displayleftmenu', 'lesson'), 'lesson')); + $mform->setDefault('displayleft', 0); + + $options = array(); + for($i = 100; $i >= 0; $i--) { + $options[$i] = $i.'%'; + } + $mform->addElement('select', 'displayleftif', get_string('displayleftif', 'lesson'), $options); + $mform->setHelpButton('displayleftif', array('displayleftif', get_string('displayleftmenuif', 'lesson'), 'lesson')); + $mform->setDefault('displayleftif', 0); + $mform->setAdvanced('displayleftif'); + $numbers = array(); for ($i = 100; $i >= 0; $i--) { $numbers[$i] = $i; @@ -122,6 +225,7 @@ class mod_lesson_mod_form extends moodleform_mod { $mform->addElement('select', 'minquestions', get_string('minimumnumberofquestions', 'lesson'), $numbers); $mform->setHelpButton('minquestions', array('minquestions', get_string('minimumnumberofquestions', 'lesson'), 'lesson')); $mform->setDefault('minquestions', 0); + $mform->setAdvanced('minquestions'); $numbers = array(); for ($i = 100; $i >= 0; $i--) { @@ -129,71 +233,47 @@ class mod_lesson_mod_form extends moodleform_mod { } $mform->addElement('select', 'maxpages', get_string('numberofpagestoshow', 'lesson'), $numbers); $mform->setHelpButton('maxpages', array('maxpages', get_string('numberofpagestoshow', 'lesson'), 'lesson')); + $mform->setAdvanced('maxpages'); $mform->setDefault('maxpages', 0); -//------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('lessonformating', 'lesson')); - $mform->addElement('selectyesno', 'slideshow', get_string('slideshow', 'lesson')); $mform->setHelpButton('slideshow', array('slideshow', get_string('slideshow', 'lesson'), 'lesson')); $mform->setDefault('slideshow', 0); + $mform->setAdvanced('slideshow'); - $mform->addElement('text', 'width', get_string('slideshowwidth', 'lesson')); - $mform->setDefault('width', 640); - $mform->addRule('width', null, 'required', null, 'client'); - $mform->addRule('width', null, 'numeric', null, 'client'); - $mform->setHelpButton('width', array('width', get_string('slideshowwidth', 'lesson'), 'lesson')); - $mform->setType('width', PARAM_INT); - - $mform->addElement('text', 'height', get_string('slideshowheight', 'lesson')); - $mform->setDefault('height', 480); - $mform->addRule('height', null, 'required', null, 'client'); - $mform->addRule('height', null, 'numeric', null, 'client'); - $mform->setHelpButton('height', array('height', get_string('slideshowheight', 'lesson'), 'lesson')); - $mform->setType('height', PARAM_INT); - - $mform->addElement('text', 'bgcolor', get_string('slideshowbgcolor', 'lesson')); - $mform->setDefault('bgcolor', '#FFFFFF'); - $mform->addRule('bgcolor', null, 'required', null, 'client'); - $mform->setHelpButton('bgcolor', array('bgcolor', get_string('slideshowbgcolor', 'lesson'), 'lesson')); - $mform->setType('bgcolor', PARAM_TEXT); + // get the modules + if ($mods = get_course_mods($COURSE->id)) { + $modinstances = array(); + foreach ($mods as $mod) { - $mform->addElement('selectyesno', 'displayleft', get_string('displayleftmenu', 'lesson')); - $mform->setHelpButton('displayleft', array('displayleft', get_string('displayleftmenu', 'lesson'), 'lesson')); - $mform->setDefault('displayleft', 0); + // get the module name and then store it in a new array + if ($module = get_coursemodule_from_instance($mod->modname, $mod->instance, $COURSE->id)) { + if (isset($this->_cm->id) and $this->_cm->id != $mod->id){ + $modinstances[$mod->id] = $mod->modname.' - '.$module->name; + } + } + } + asort($modinstances); // sort by module name + $modinstances=array(0=>get_string('none'))+$modinstances; - $options = array(); - for($i = 100; $i >= 0; $i--) { - $options[$i] = $i.'%'; + $mform->addElement('select', 'activitylink', get_string('activitylink', 'lesson'), $modinstances); + $mform->setHelpButton('activitylink', array('activitylink', get_string('activitylink', 'lesson'), 'lesson')); + $mform->setDefault('activitylink', 0); + $mform->setAdvanced('activitylink'); } - $mform->addElement('select', 'displayleftif', get_string('displayleftif', 'lesson'), $options); - $mform->setDefault('displayleftif', 0); - - $mform->addElement('selectyesno', 'progressbar', get_string('progressbar', 'lesson')); - $mform->setHelpButton('progressbar', array('progressbar', get_string('progressbar', 'lesson'), 'lesson')); - $mform->setDefault('progressbar', 0); - //------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('accesscontrol', 'lesson')); + $mform->addElement('header', 'mediafileheader', get_string('mediafile', 'lesson')); - $mform->addElement('selectyesno', 'usepassword', get_string('usepassword', 'lesson')); - $mform->setHelpButton('usepassword', array('usepassword', get_string('usepassword', 'lesson'), 'lesson')); - $mform->setDefault('usepassword', 0); - - $mform->addElement('passwordunmask', 'password', get_string('password', 'lesson')); - $mform->setHelpButton('password', array('password', get_string('password', 'lesson'), 'lesson')); - $mform->setDefault('password', ''); - $mform->setType('password', PARAM_RAW); - - $mform->addElement('date_time_selector', 'available', get_string('available', 'lesson'), array('optional'=>true)); - $mform->setDefault('available', 0); - - $mform->addElement('date_time_selector', 'deadline', get_string('deadline', 'lesson'), array('optional'=>true)); - $mform->setDefault('deadline', 0); + $filepickeroptions = array(); + $filepickeroptions['filetypes'] = '*'; + $filepickeroptions['maxbytes'] = $this->course->maxbytes; + $mform->addElement('filepicker', 'mediafile', get_string('mediafile', 'lesson'), null, $filepickeroptions); + $mform->setHelpButton('mediafile', array('mediafile', get_string('mediafile', 'lesson'), 'lesson')); + $mform->setDefault('mediafile', ''); //------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('dependencyon', 'lesson')); + $mform->addElement('header', 'dependencyon', get_string('dependencyon', 'lesson')); $options = array(0=>get_string('none')); if ($lessons = get_all_instances_in_course('lesson', $COURSE)) { @@ -219,66 +299,6 @@ class mod_lesson_mod_form extends moodleform_mod { $mform->setDefault('gradebetterthan', 0); $mform->setType('gradebetterthan', PARAM_INT); -//------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('mediafile', 'lesson')); - - $mform->addElement('choosecoursefile', 'mediafile', get_string('mediafile', 'lesson'), array('courseid'=>$COURSE->id)); - $mform->setHelpButton('mediafile', array('mediafile', get_string('mediafile', 'lesson'), 'lesson')); - $mform->setDefault('mediafile', ''); - $mform->setType('mediafile', PARAM_RAW); - - $mform->addElement('selectyesno', 'mediaclose', get_string('mediaclose', 'lesson')); - $mform->setDefault('mediaclose', 0); - - $mform->addElement('text', 'mediaheight', get_string('mediaheight', 'lesson')); - $mform->setHelpButton('mediaheight', array('mediaheight', get_string('mediaheight', 'lesson'), 'lesson')); - $mform->setDefault('mediaheight', 100); - $mform->addRule('mediaheight', null, 'required', null, 'client'); - $mform->addRule('mediaheight', null, 'numeric', null, 'client'); - $mform->setType('mediaheight', PARAM_INT); - - $mform->addElement('text', 'mediawidth', get_string('mediawidth', 'lesson')); - $mform->setHelpButton('mediawidth', array('mediawidth', get_string('mediawidth', 'lesson'), 'lesson')); - $mform->setDefault('mediawidth', 650); - $mform->addRule('mediawidth', null, 'required', null, 'client'); - $mform->addRule('mediawidth', null, 'numeric', null, 'client'); - $mform->setType('mediawidth', PARAM_INT); - -//------------------------------------------------------------------------------- - $mform->addElement('header', '', get_string('other', 'lesson')); - - // get the modules - if ($mods = get_course_mods($COURSE->id)) { - $modinstances = array(); - foreach ($mods as $mod) { - - // get the module name and then store it in a new array - if ($module = get_coursemodule_from_instance($mod->modname, $mod->instance, $COURSE->id)) { - if (isset($this->_cm->id) and $this->_cm->id != $mod->id){ - $modinstances[$mod->id] = $mod->modname.' - '.$module->name; - } - } - } - asort($modinstances); // sort by module name - $modinstances=array(0=>get_string('none'))+$modinstances; - - $mform->addElement('select', 'activitylink', get_string('activitylink', 'lesson'), $modinstances); - $mform->setHelpButton('activitylink', array('activitylink', get_string('activitylink', 'lesson'), 'lesson')); - $mform->setDefault('activitylink', 0); - - } - - $mform->addElement('text', 'maxhighscores', get_string('maxhighscores', 'lesson')); - $mform->setHelpButton('maxhighscores', array('maxhighscores', get_string('maxhighscores', 'lesson'), 'lesson')); - $mform->setDefault('maxhighscores', 10); - $mform->addRule('maxhighscores', null, 'required', null, 'client'); - $mform->addRule('maxhighscores', null, 'numeric', null, 'client'); - $mform->setType('maxhighscores', PARAM_INT); - - $mform->addElement('selectyesno', 'lessondefault', get_string('lessondefault', 'lesson')); - $mform->setHelpButton('lessondefault', array('lessondefault', get_string('lessondefault', 'lesson'), 'lesson')); - $mform->setDefault('lessondefault', 0); - //------------------------------------------------------------------------------- $this->standard_coursemodule_elements(); //------------------------------------------------------------------------------- @@ -305,20 +325,11 @@ class mod_lesson_mod_form extends moodleform_mod { if (isset($default_values['password']) and ($module->version<2008112600)) { unset($default_values['password']); } - if (isset($default_values['add']) and $defaults = $DB->get_record('lesson_default', array('course' => $default_values['course']))) { - foreach ($defaults as $fieldname => $default) { - switch ($fieldname) { - case 'conditions': - $conditions = unserialize($default); - $default_values['timespent'] = $conditions->timespent; - $default_values['completed'] = $conditions->completed; - $default_values['gradebetterthan'] = $conditions->gradebetterthan; - break; - default: - $default_values[$fieldname] = $default; - break; - } - } + if (!empty($this->_cm) && !empty($default_values['mediafile'])) { + $context = get_context_instance(CONTEXT_MODULE, $this->_cm->id); + $draftitemid = file_get_submitted_draft_itemid('mediafile'); + file_prepare_draft_area($draftitemid, $context->id, 'lesson_media_file', $this->_cm->instance, array('subdirs' => 0, 'maxbytes' => $this->course->maxbytes, 'maxfiles' => 1)); + $default_values['mediafile'] = $draftitemid; } } diff --git a/mod/lesson/pagetypes/branchtable.php b/mod/lesson/pagetypes/branchtable.php new file mode 100644 index 0000000000..9c59b1542b --- /dev/null +++ b/mod/lesson/pagetypes/branchtable.php @@ -0,0 +1,296 @@ +. + +/** + * Branch Table + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** Branch Table page */ +define("LESSON_PAGE_BRANCHTABLE", "20"); + +class lesson_page_type_branchtable extends lesson_page { + + protected $type = lesson_page::TYPE_STRUCTURE; + protected $typeid = LESSON_PAGE_BRANCHTABLE; + protected $typeidstring = 'branchtable'; + protected $string = null; + protected $jumpto = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public static function get_jumptooptions($firstpage, $lesson) { + global $DB, $PAGE; + $jump = array(); + $jump[0] = get_string("thispage", "lesson"); + $jump[LESSON_NEXTPAGE] = get_string("nextpage", "lesson"); + $jump[LESSON_PREVIOUSPAGE] = get_string("previouspage", "lesson"); + $jump[LESSON_EOL] = get_string("endoflesson", "lesson"); + if (!$firstpage) { + if (!$apageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0))) { + print_error('cannotfindfirstpage', 'lesson'); + } + while (true) { + if ($apageid) { + $title = $DB->get_field("lesson_pages", "title", array("id" => $apageid)); + $jump[$apageid] = $title; + $apageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $apageid)); + } else { + // last page reached + break; + } + } + } + return $jump; + } + public function get_idstring() { + return $this->typeidstring; + } + public function display($renderer, $attempt) { + global $PAGE, $CFG; + + $output = ''; + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + if ($this->lesson->slideshow) { + $output .= $renderer->slideshow_start($this->lesson); + } + $output .= $renderer->heading(format_string($this->properties->title)); + $output .= $renderer->box($this->get_contents(), 'contents'); + + $buttons = array(); + $i = 0; + foreach ($this->get_answers() as $answer) { + $params = array(); + $params['id'] = $PAGE->cm->id; + $params['pageid'] = $this->properties->id; + $params['sesskey'] = sesskey(); + $params['jumpto'] = $answer->jumpto; + $buttons[] = $renderer->button(html_form::make_button($CFG->wwwroot.'/mod/lesson/continue.php', $params, strip_tags(format_text($answer->answer, FORMAT_MOODLE, $options)))); + $i++; + } + // Set the orientation + if ($this->properties->layout) { + $buttonshtml = $renderer->box(implode("\n", $buttons), 'branchbuttoncontainer horizontal'); + } else { + $buttonshtml = $renderer->box(implode("\n", $buttons), 'branchbuttoncontainer vertical'); + } + $output .= $buttonshtml; + + if ($this->lesson->slideshow) { + $output .= $renderer->slideshow_end(); + } + + return $output; + } + + public function check_answer() { + global $USER, $DB, $PAGE, $CFG; + + require_sesskey(); + $newpageid = optional_param('jumpto', NULL, PARAM_INT); + // going to insert into lesson_branch + if ($newpageid == LESSON_RANDOMBRANCH) { + $branchflag = 1; + } else { + $branchflag = 0; + } + if ($grades = $DB->get_records("lesson_grades", array("lessonid" => $this->lesson->id, "userid" => $USER->id), "grade DESC")) { + $retries = count($grades); + } else { + $retries = 0; + } + $branch = new stdClass; + $branch->lessonid = $this->lesson->id; + $branch->userid = $USER->id; + $branch->pageid = $this->properties->id; + $branch->retry = $retries; + $branch->flag = $branchflag; + $branch->timeseen = time(); + + $DB->insert_record("lesson_branch", $branch); + + // this is called when jumping to random from a branch table + $context = get_context_instance(CONTEXT_MODULE, $PAGE->cm->id); + if($newpageid == LESSON_UNSEENBRANCHPAGE) { + if (has_capability('mod/lesson:manage', $context)) { + $newpageid = LESSON_NEXTPAGE; + } else { + $newpageid = lesson_unseen_question_jump($this->lesson, $USER->id, $this->properties->id); // this may return 0 + } + } + // convert jumpto page into a proper page id + if ($newpageid == 0) { + $newpageid = $this->properties->id; + } elseif ($newpageid == LESSON_NEXTPAGE) { + if (!$newpageid = $this->nextpageid) { + // no nextpage go to end of lesson + $newpageid = LESSON_EOL; + } + } elseif ($newpageid == LESSON_PREVIOUSPAGE) { + $newpageid = $page->prevpageid; + } elseif ($newpageid == LESSON_RANDOMPAGE) { + $newpageid = lesson_random_question_jump($this->lesson, $this->properties->id); + } elseif ($newpageid == LESSON_RANDOMBRANCH) { + $newpageid = lesson_unseen_branch_jump($this->lesson, $USER->id); + } + // no need to record anything in lesson_attempts + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id,'pageid'=>$newpageid))); + } + + public function display_answers($table) { + $answers = $this->get_answers(); + $options = new stdClass; + $options->noclean = true; + $options->para = false; + $i = 1; + foreach ($answers as $answer) { + $cells = array(); + $cells[] = "".get_string("branch", "lesson")." $i: "; + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("jump", "lesson")." $i: "; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + $i++; + } + return $table; + } + public function get_grayout() { + return 1; + } + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + $data = "id\" value=\"".strip_tags(format_text($answer->answer, FORMAT_MOODLE,$formattextdefoptions))."\" disabled=\"disabled\"> "; + $data .= get_string('jumpsto', 'lesson', $this->get_jump_name($answer->jumpto)); + $answerdata->answers[] = array($data, ""); + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } + + public function update($properties) { + if (empty($properties->display)) { + $properties->display = '0'; + } + if (empty($properties->layout)) { + $properties->layout = '0'; + } + return parent::update($properties); + } + public function add_page_link($previd) { + global $PAGE, $CFG; + $addbranchurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$PAGE->cm->id, 'pageid'=>$previd, 'qtype'=>LESSON_PAGE_BRANCHTABLE)); + return html_link::make($addbranchurl, get_string('addabranchtable', 'lesson')); + } + protected function get_displayinmenublock() { + return true; + } + public function is_unseen($param) { + global $USER, $DB; + if (is_array($param)) { + $seenpages = $param; + $branchpages = $this->lesson->get_sub_pages_of($this->properties->id, array(LESSON_PAGE_BRANCHTABLE, LESSON_PAGE_ENDOFBRANCH)); + foreach ($branchpages as $branchpage) { + if (array_key_exists($branchpage->id, $seenpages)) { // check if any of the pages have been viewed + return false; + } + } + return true; + } else { + $nretakes = $param; + if (!$DB->count_records("lesson_attempts", array("pageid"=>$this->properties->id, "userid"=>$USER->id, "retry"=>$nretakes))) { + return true; + } + return false; + } + } +} + +class lesson_add_page_form_branchtable extends lesson_add_page_form_base { + + public $qtype = LESSON_PAGE_BRANCHTABLE; + public $qtypestring = 'branchtable'; + protected $standard = false; + + public function custom_definition() { + global $PAGE; + + $mform = $this->_form; + $lesson = $this->_customdata['lesson']; + + $firstpage = optional_param('firstpage', false, PARAM_BOOL); + + $jumptooptions = lesson_page_type_branchtable::get_jumptooptions($firstpage, $lesson); + + $mform->setDefault('qtypeheading', get_string('addabranchtable', 'lesson')); + + $mform->addElement('hidden', 'firstpage'); + $mform->setType('firstpage', PARAM_BOOL); + $mform->setDefault('firstpage', $firstpage); + + $mform->addElement('hidden', 'qtype'); + $mform->setType('qtype', PARAM_INT); + + $mform->addElement('text', 'title', get_string("pagetitle", "lesson"), array('size'=>70)); + $mform->setType('title', PARAM_TEXT); + + $this->editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes); + $mform->addElement('editor', 'contents_editor', get_string("pagecontents", "lesson"), null, $this->editoroptions); + $mform->setType('contents_editor', PARAM_CLEANHTML); + + $mform->addElement('checkbox', 'layout', null, get_string("arrangebuttonshorizontally", "lesson")); + $mform->setDefault('layout', true); + + $mform->addElement('checkbox', 'display', null, get_string("displayinleftmenu", "lesson")); + $mform->setDefault('display', true); + + for ($i = 0; $i < $lesson->maxanswers; $i++) { + $mform->addElement('header', 'headeranswer'.$i, get_string('branch', 'lesson').' '.($i+1)); + $mform->addElement('textarea', 'answer['.$i.']', get_string("description", "lesson"), array('rows'=>10, 'cols'=>70, 'width'=>630, 'height'=>300)); + $mform->setType('answer['.$i.']', PARAM_CLEANHTML); + + $mform->addElement('select', 'jumpto['.$i.']', get_string("jump", "lesson"), $jumptooptions); + if ($i === 0) { + $mform->setDefault('jumpto['.$i.']', 0); + } else { + $mform->setDefault('jumpto['.$i.']', LESSON_NEXTPAGE); + } + } + } +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/cluster.php b/mod/lesson/pagetypes/cluster.php new file mode 100644 index 0000000000..89af66578a --- /dev/null +++ b/mod/lesson/pagetypes/cluster.php @@ -0,0 +1,176 @@ +. + +/** + * Cluster + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** Start of Cluster page */ +define("LESSON_PAGE_CLUSTER", "30"); + +class lesson_page_type_cluster extends lesson_page { + + protected $type = lesson_page::TYPE_STRUCTURE; + protected $typeidstring = 'cluster'; + protected $typeid = LESSON_PAGE_CLUSTER; + protected $string = null; + protected $jumpto = null; + + public function display($renderer, $attempt) { + return ''; + } + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function get_grayout() { + return 1; + } + public function callback_on_view($canmanage) { + global $USER; + if (!$canmanage) { + // Get the next page in the lesson cluster jump + return $this->lesson->cluster_jump($this->properties->id); + } else { + // get the next page + return $this->properties->nextpageid; + } + } + public function override_next_page() { + global $USER; + return $this->lesson->cluster_jump($this->properties->id); + } + public function add_page_link($previd) { + global $PAGE, $CFG; + $addclusterurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$PAGE->cm->id, 'pageid'=>$previd, 'sesskey'=>sesskey(), 'qtype'=>LESSON_PAGE_CLUSTER)); + return html_link::make($addclusterurl, get_string('addcluster', 'lesson')); + } + public function valid_page_and_view(&$validpages, &$pageviews) { + $validpages[$this->properties->id] = 1; // add the cluster page as a valid page + foreach ($this->lesson->get_sub_pages_of($this->properties->id, array(LESSON_PAGE_ENDOFCLUSTER)) as $subpage) { + if (in_array($subpage->id, $pageviews)) { + unset($pageviews[array_search($subpage->id, $pageviews)]); // remove it + // since the user did see one page in the cluster, add the cluster pageid to the viewedpageids + if (!in_array($this->properties->id, $pageviews)) { + $pageviews[] = $this->properties->id; + } + } + } + return $this->properties->nextpageid; + } +} + +class lesson_add_page_form_cluster extends lesson_add_page_form_base { + + public $qtype = LESSON_PAGE_CLUSTER; + public $qtypestring = 'cluster'; + protected $standard = false; + + public function custom_definition() { + global $PAGE; + + $mform = $this->_form; + $lesson = $this->_customdata['lesson']; + $jumptooptions = lesson_page_type_branchtable::get_jumptooptions(optional_param('firstpage', false, PARAM_BOOL), $lesson); + + $mform->addElement('hidden', 'firstpage'); + $mform->setType('firstpage', PARAM_BOOL); + + $mform->addElement('hidden', 'qtype'); + $mform->setType('qtype', PARAM_TEXT); + + $mform->addElement('text', 'title', get_string("pagetitle", "lesson"), array('size'=>70)); + $mform->setType('title', PARAM_TEXT); + + $this->editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes); + $mform->addElement('editor', 'contents_editor', get_string("pagecontents", "lesson"), null, $this->editoroptions); + $mform->setType('contents_editor', PARAM_CLEANHTML); + + $this->add_jumpto(0); + } + + + public function construction_override($pageid, lesson $lesson) { + global $PAGE, $CFG, $DB; + require_sesskey(); + + $timenow = time(); + + if ($pageid == 0) { + if ($lesson->has_pages()) { + if (!$page = $DB->get_record("lesson_pages", array("prevpageid" => 0, "lessonid" => $lesson->id))) { + print_error('cannotfindpagerecord', 'lesson'); + } + } else { + // This is the ONLY page + $page = new stdClass; + $page->id = 0; + } + } else { + if (!$page = $DB->get_record("lesson_pages", array("id" => $pageid))) { + print_error('cannotfindpagerecord', 'lesson'); + } + } + $newpage = new stdClass; + $newpage->lessonid = $lesson->id; + $newpage->prevpageid = $pageid; + if ($pageid != 0) { + $newpage->nextpageid = $page->nextpageid; + } else { + $newpage->nextpageid = $page->id; + } + $newpage->qtype = $this->qtype; + $newpage->timecreated = $timenow; + $newpage->title = get_string("clustertitle", "lesson"); + $newpage->contents = get_string("clustertitle", "lesson"); + $newpageid = $DB->insert_record("lesson_pages", $newpage); + // update the linked list... + if ($pageid != 0) { + $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); + } + + if ($pageid == 0) { + $page->nextpageid = $page->id; + } + if ($page->nextpageid) { + // the new page is not the last page + $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); + } + // ..and the single "answer" + $newanswer = new stdClass; + $newanswer->lessonid = $lesson->id; + $newanswer->pageid = $newpageid; + $newanswer->timecreated = $timenow; + $newanswer->jumpto = LESSON_CLUSTERJUMP; + $newanswerid = $DB->insert_record("lesson_answers", $newanswer); + $lesson->add_message(get_string('addedcluster', 'lesson'), 'notifysuccess'); + redirect($CFG->wwwroot.'/mod/lesson/edit.php?id='.$PAGE->cm->id); + } +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/endofbranch.php b/mod/lesson/pagetypes/endofbranch.php new file mode 100644 index 0000000000..4dd7c23c00 --- /dev/null +++ b/mod/lesson/pagetypes/endofbranch.php @@ -0,0 +1,230 @@ +. + +/** + * End of branch table + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** End of Branch page */ +define("LESSON_PAGE_ENDOFBRANCH", "21"); + +class lesson_page_type_endofbranch extends lesson_page { + + protected $type = lesson_page::TYPE_STRUCTURE; + protected $typeidstring = 'endofbranch'; + protected $typeid = LESSON_PAGE_ENDOFBRANCH; + protected $string = null; + protected $jumpto = null; + + public function display($renderer, $attempt) { + return ''; + } + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function callback_on_view($canmanage) { + $this->redirect_to_first_answer(); + exit; + } + + public function redirect_to_first_answer($canmanager) { + global $USER, $PAGE; + $answer = array_shift($this->get_answers()); + $jumpto = $answer->jumpto; + if ($jumpto == LESSON_RANDOMBRANCH) { + + $jumpto = lesson_unseen_branch_jump($this->lesson, $USER->id); + + } elseif ($jumpto == LESSON_CLUSTERJUMP) { + + if (!$canmanage) { + $jumpto = $this->lesson->cluster_jump($pageid); + } else { + if ($this->properties->nextpageid == 0) { + $jumpto = LESSON_EOL; + } else { + $jumpto = $this->properties->nextpageid; + } + } + + } else if ($answer->jumpto == LESSON_NEXTPAGE) { + + if ($this->properties->nextpageid == 0) { + $jumpto = LESSON_EOL; + } else { + $jumpto = $this->properties->nextpageid; + } + + } else if ($jumpto == 0) { + + $jumpto = $this->properties->id; + + } else if ($jumpto == LESSON_PREVIOUSPAGE) { + + $jumpto = $this->properties->prevpageid; + + } + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id,'pageid'=>$jumpto))); + } + public function get_grayout() { + return 1; + } + public function update($properties) { + global $DB, $PAGE; + + $properties->id = $this->properties->id; + $properties->lessonid = $this->lesson->id; + if (empty($properties->qoption)) { + $properties->qoption = '0'; + } + $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes), get_context_instance(CONTEXT_MODULE, $PAGE->cm->id), 'lesson_page_contents', $properties->id); + $DB->update_record("lesson_pages", $properties); + + $answers = $this->get_answers(); + if (count($answers)>1) { + $answer = array_shift($answers); + foreach ($answers as $a) { + $DB->delete_record('lesson_answers', array('id'=>$a->id)); + } + } else if (count($answers)==1) { + $answer = array_shift($answers); + } else { + $answer = new stdClass; + } + + $answer->timemodified = time();; + if (isset($properties->jumpto[0])) { + $answer->jumpto = $properties->jumpto[0]; + } + if (isset($form->score[0])) { + $answer->score = $properties->score[0]; + } + if (!empty($answer->id)) { + $DB->update_record("lesson_answers", $answer->properties()); + } else { + $DB->insert_record("lesson_answers", $answer); + } + return true; + } + public function add_page_link($previd) { + global $PAGE, $CFG; + if ($previd != 0) { + $addendofbranchurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$PAGE->cm->id, 'pageid'=>$previd, 'sesskey'=>sesskey(), 'qtype'=>LESSON_PAGE_ENDOFBRANCH)); + return html_link::make($addendofbranchurl, get_string('addanendofbranch', 'lesson')); + } + return false; + } + public function valid_page_and_view(&$validpages, &$pageviews) { + return $this->properties->nextpageid; + } +} + +class lesson_add_page_form_endofbranch extends lesson_add_page_form_base { + + public $qtype = LESSON_PAGE_ENDOFBRANCH; + public $qtypestring = 'endofbranch'; + protected $standard = false; + + public function custom_definition() { + global $PAGE; + + $mform = $this->_form; + $lesson = $this->_customdata['lesson']; + $jumptooptions = lesson_page_type_branchtable::get_jumptooptions(optional_param('firstpage', false, PARAM_BOOL), $lesson); + + $mform->addElement('hidden', 'firstpage'); + $mform->setType('firstpage', PARAM_BOOL); + + $mform->addElement('hidden', 'qtype'); + $mform->setType('qtype', PARAM_TEXT); + + $mform->addElement('text', 'title', get_string("pagetitle", "lesson"), array('size'=>70)); + $mform->setType('title', PARAM_TEXT); + + $this->editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes); + $mform->addElement('editor', 'contents_editor', get_string("pagecontents", "lesson"), null, $this->editoroptions); + $mform->setType('contents_editor', PARAM_CLEANHTML); + + $this->add_jumpto(0); + } + + public function construction_override($pageid, $lesson) { + global $DB, $CFG, $PAGE; + require_sesskey(); + + // first get the preceeding page + + $timenow = time(); + + // the new page is not the first page (end of branch always comes after an existing page) + if (!$page = $DB->get_record("lesson_pages", array("id" => $pageid))) { + print_error('cannotfindpagerecord', 'lesson'); + } + // chain back up to find the (nearest branch table) + $btpage = clone($page); + $btpageid = $btpage->id; + while (($btpage->qtype != LESSON_PAGE_BRANCHTABLE) && ($btpage->prevpageid > 0)) { + $btpageid = $btpage->prevpageid; + if (!$btpage = $DB->get_record("lesson_pages", array("id" => $btpageid))) { + print_error('cannotfindpagerecord', 'lesson'); + } + } + + if ($btpage->qtype == LESSON_PAGE_BRANCHTABLE) { + $newpage = new stdClass; + $newpage->lessonid = $lesson->id; + $newpage->prevpageid = $pageid; + $newpage->nextpageid = $page->nextpageid; + $newpage->qtype = $this->qtype; + $newpage->timecreated = $timenow; + $newpage->title = get_string("endofbranch", "lesson"); + $newpage->contents = get_string("endofbranch", "lesson"); + $newpageid = $DB->insert_record("lesson_pages", $newpage); + // update the linked list... + $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); + if ($page->nextpageid) { + // the new page is not the last page + $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); + } + // ..and the single "answer" + $newanswer = new stdClass; + $newanswer->lessonid = $lesson->id; + $newanswer->pageid = $newpageid; + $newanswer->timecreated = $timenow; + $newanswer->jumpto = $btpageid; + $newanswerid = $DB->insert_record("lesson_answers", $newanswer); + $lesson->add_message(get_string('addedanendofbranch', 'lesson'), 'notifysuccess'); + } else { + $lesson->add_message(get_string('nobranchtablefound', 'lesson')); + } + + redirect($CFG->wwwroot."/mod/lesson/edit.php?id=".$PAGE->cm->id); + } +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/endofcluster.php b/mod/lesson/pagetypes/endofcluster.php new file mode 100644 index 0000000000..4913383507 --- /dev/null +++ b/mod/lesson/pagetypes/endofcluster.php @@ -0,0 +1,197 @@ +. + +/** + * End of cluster + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** End of Cluster page */ +define("LESSON_PAGE_ENDOFCLUSTER", "31"); + +class lesson_page_type_endofcluster extends lesson_page { + + protected $type = lesson_page::TYPE_STRUCTURE; + protected $typeidstring = 'endofcluster'; + protected $typeid = LESSON_PAGE_ENDOFCLUSTER; + protected $string = null; + protected $jumpto = null; + + public function display($renderer, $attempt) { + return ''; + } + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function callback_on_view($canmanage) { + $this->redirect_to_next_page($canmanage); + exit; + } + public function redirect_to_next_page() { + global $PAGE; + if ($this->properties->nextpageid == 0) { + $nextpageid = LESSON_EOL; + } else { + $nextpageid = $this->properties->nextpageid; + } + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id,'pageid'=>$nextpageid))); + } + public function get_grayout() { + return 1; + } + public function update($properties) { + global $DB, $PAGE; + + $properties->id = $this->properties->id; + $properties->lessonid = $this->lesson->id; + if (empty($properties->qoption)) { + $properties->qoption = '0'; + } + $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes), get_context_instance(CONTEXT_MODULE, $PAGE->cm->id), 'lesson_page_contents', $properties->id); + $DB->update_record("lesson_pages", $properties); + + $answers = $this->get_answers(); + if (count($answers)>1) { + $answer = array_shift($answers); + foreach ($answers as $a) { + $DB->delete_record('lesson_answers', array('id'=>$a->id)); + } + } else if (count($answers)==1) { + $answer = array_shift($answers); + } else { + $answer = new stdClass; + } + + $answer->timemodified = time();; + if (isset($properties->jumpto[0])) { + $answer->jumpto = $properties->jumpto[0]; + } + if (isset($form->score[0])) { + $answer->score = $properties->score[0]; + } + if (!empty($answer->id)) { + $DB->update_record("lesson_answers", $answer->properties()); + } else { + $DB->insert_record("lesson_answers", $answer); + } + return true; + } + public function override_next_page() { + $jump = $DB->get_field("lesson_answers", "jumpto", array("pageid" => $this->properties->id, "lessonid" => $this->lesson->id)); + if ($jump == LESSON_NEXTPAGE) { + if ($this->properties->nextpageid == 0) { + return LESSON_EOL; + } else { + return $this->properties->nextpageid; + } + } else { + return $jump; + } + } + public function add_page_link($previd) { + global $PAGE, $CFG; + if ($previd != 0) { + $endofclusterurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$PAGE->cm->id, 'pageid'=>$previd, 'sesskey'=>sesskey(), 'qtype'=>LESSON_PAGE_ENDOFCLUSTER)); + return html_link::make($endofclusterurl, get_string('addendofcluster', 'lesson')); + } + return false; + } + public function valid_page_and_view(&$validpages, &$pageviews) { + return $this->properties->nextpageid; + } +} + +class lesson_add_page_form_endofcluster extends lesson_add_page_form_base { + + public $qtype = LESSON_PAGE_ENDOFCLUSTER; + public $qtypestring = 'endofcluster'; + protected $standard = false; + + public function custom_definition() { + global $PAGE; + + $mform = $this->_form; + $lesson = $this->_customdata['lesson']; + $jumptooptions = lesson_page_type_branchtable::get_jumptooptions(optional_param('firstpage', false, PARAM_BOOL), $lesson); + + $mform->addElement('hidden', 'firstpage'); + $mform->setType('firstpage', PARAM_BOOL); + + $mform->addElement('hidden', 'qtype'); + $mform->setType('qtype', PARAM_TEXT); + + $mform->addElement('text', 'title', get_string("pagetitle", "lesson"), array('size'=>70)); + $mform->setType('title', PARAM_TEXT); + + $this->editoroptions = array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes); + $mform->addElement('editor', 'contents_editor', get_string("pagecontents", "lesson"), null, $this->editoroptions); + $mform->setType('contents_editor', PARAM_CLEANHTML); + + $this->add_jumpto(0); + } + + public function construction_override($pageid, $lesson) { + global $CFG, $PAGE, $DB; + require_sesskey(); + + $timenow = time(); + + // the new page is not the first page (end of cluster always comes after an existing page) + if (!$page = $DB->get_record("lesson_pages", array("id" => $pageid))) { + print_error('cannotfindpages', 'lesson'); + } + + // could put code in here to check if the user really can insert an end of cluster + + $newpage = new stdClass; + $newpage->lessonid = $lesson->id; + $newpage->prevpageid = $pageid; + $newpage->nextpageid = $page->nextpageid; + $newpage->qtype = $this->qtype; + $newpage->timecreated = $timenow; + $newpage->title = get_string("endofclustertitle", "lesson"); + $newpage->contents = get_string("endofclustertitle", "lesson"); + $newpageid = $DB->insert_record("lesson_pages", $newpage); + // update the linked list... + $DB->set_field("lesson_pages", "nextpageid", $newpageid, array("id" => $pageid)); + if ($page->nextpageid) { + // the new page is not the last page + $DB->set_field("lesson_pages", "prevpageid", $newpageid, array("id" => $page->nextpageid)); + } + // ..and the single "answer" + $newanswer = new stdClass; + $newanswer->lessonid = $lesson->id; + $newanswer->pageid = $newpageid; + $newanswer->timecreated = $timenow; + $newanswer->jumpto = LESSON_NEXTPAGE; + $newanswerid = $DB->insert_record("lesson_answers", $newanswer); + $lesson->add_message(get_string('addedendofcluster', 'lesson'), 'notifysuccess'); + redirect($CFG->wwwroot.'/mod/lesson/edit.php?id='.$PAGE->cm->id); + } +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/essay.php b/mod/lesson/pagetypes/essay.php new file mode 100644 index 0000000000..4a0f07cd8c --- /dev/null +++ b/mod/lesson/pagetypes/essay.php @@ -0,0 +1,270 @@ +. + +/** + * Essay + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** Essay question type */ +define("LESSON_PAGE_ESSAY", "10"); + +class lesson_page_type_essay extends lesson_page { + + protected $type = lesson_page::TYPE_QUESTION; + protected $typeidstring = 'essay'; + protected $typeid = LESSON_PAGE_ESSAY; + protected $string = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function display($renderer, $attempt) { + global $PAGE, $CFG; + + $mform = new lesson_display_answer_form_essay($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); + + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->pageid = $this->properties->id; + if (isset($USER->modattempts[$this->lesson->id])) { + $essayinfo = unserialize($attempt->useranswer); + $data->answer = array('text'=>$essayinfo->answer, 'format'=>FORMAT_HTML); + } + $mform->set_data($data); + return $mform->display(); + } + public function create_answers($properties) { + global $DB; + // now add the answers + $newanswer = new stdClass; + $newanswer->lessonid = $this->lesson->id; + $newanswer->pageid = $this->properties->id; + $newanswer->timecreated = $this->properties->timecreated; + + if (isset($properties->jumpto[0])) { + $newanswer->jumpto = $properties->jumpto[0]; + } + if (isset($properties->score[0])) { + $newanswer->score = $properties->score[0]; + } + $newanswer->id = $DB->insert_record("lesson_answers", $newanswer); + $answers = array($newanswer->id => new lesson_page_answer($newanswer)); + $this->answers = $answers; + return $answers; + } + public function check_answer() { + global $PAGE, $CFG; + $result = parent::check_answer(); + $result->isessayquestion = true; + + $mform = new lesson_display_answer_form_essay($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); + $data = $mform->get_data(); + require_sesskey(); + + if (!$data) { + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$this->properties->id))); + } + + $studentanswer = $data->answer['text']; + if (trim($studentanswer) === '') { + $result->noanswer = true; + return $result; + } + + $answers = $this->get_answers(); + foreach ($answers as $answer) { + $result->answerid = $answer->id; + $result->newpageid = $answer->jumpto; + } + + $userresponse = new stdClass; + $userresponse->sent=0; + $userresponse->graded = 0; + $userresponse->score = 0; + $userresponse->answer = $studentanswer; + $userresponse->response = ""; + $result->userresponse = serialize($userresponse); + + $result->studentanswer = s($studentanswer); + return $result; + } + public function update($properties) { + global $DB, $PAGE; + $answers = $this->get_answers(); + $properties->id = $this->properties->id; + $properties->lessonid = $this->lesson->id; + $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes), get_context_instance(CONTEXT_MODULE, $PAGE->cm->id), 'lesson_page_contents', $properties->id); + $DB->update_record("lesson_pages", $properties); + + if (!array_key_exists(0, $this->answers)) { + $this->answers[0] = new stdClass; + $this->answers[0]->lessonid = $this->lesson->id; + $this->answers[0]->pageid = $this->id; + $this->answers[0]->timecreated = $this->timecreated; + } + if (isset($properties->jumpto[0])) { + $this->answers[0]->jumpto = $properties->jumpto[0]; + } + if (isset($properties->score[0])) { + $this->answers[0]->score = $properties->score[0]; + } + if (!isset($this->answers[0]->id)) { + $this->answers[0]->id = $DB->insert_record("lesson_answers", $this->answers[0]); + } else { + $DB->update_record("lesson_answers", $this->answers[0]->properties()); + } + + return true; + } + public function stats(array &$pagestats, $tries) { + if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt + $temp = $tries[$this->lesson->maxattempts - 1]; + } else { + // else, user attempted the question less than the max, so grab the last one + $temp = end($tries); + } + $essayinfo = unserialize($temp->useranswer); + if ($essayinfo->graded) { + if (isset($pagestats[$temp->pageid])) { + $essaystats = $pagestats[$temp->pageid]; + $essaystats->totalscore += $essayinfo->score; + $essaystats->total++; + $pagestats[$temp->pageid] = $essaystats; + } else { + $essaystats->totalscore = $essayinfo->score; + $essaystats->total = 1; + $pagestats[$temp->pageid] = $essaystats; + } + } + return true; + } + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + if ($useranswer != NULL) { + $essayinfo = unserialize($useranswer->useranswer); + if ($essayinfo->response == NULL) { + $answerdata->response = get_string("nocommentyet", "lesson"); + } else { + $answerdata->response = s($essayinfo->response); + } + if (isset($pagestats[$this->properties->id])) { + $percent = $pagestats[$this->properties->id]->totalscore / $pagestats[$this->properties->id]->total * 100; + $percent = round($percent, 2); + $percent = get_string("averagescore", "lesson").": ". $percent ."%"; + } else { + // dont think this should ever be reached.... + $percent = get_string("nooneansweredthisquestion", "lesson"); + } + if ($essayinfo->graded) { + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$essayinfo->score; + } elseif ($essayinfo->score) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } else { + $answerdata->score = get_string("havenotgradedyet", "lesson"); + } + } else { + $essayinfo->answer = get_string("didnotanswerquestion", "lesson"); + } + + if (isset($pagestats[$this->properties->id])) { + $avescore = $pagestats[$this->properties->id]->totalscore / $pagestats[$this->properties->id]->total; + $avescore = round($avescore, 2); + $avescore = get_string("averagescore", "lesson").": ". $avescore ; + } else { + // dont think this should ever be reached.... + $avescore = get_string("nooneansweredthisquestion", "lesson"); + } + $answerdata->answers[] = array(s($essayinfo->answer), $avescore); + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } + public function is_unanswered($nretakes) { + global $DB, $USER; + if (!$DB->count_records("lesson_attempts", array('pageid'=>$thispage->id, 'userid'=>$USER->id, 'retry'=>$nretakes))) { + return true; + } + return false; + } + public function requires_manual_grading() { + return true; + } + public function get_earnedscore($answers, $attempt) { + $essayinfo = unserialize($attempt->useranswer); + return $essayinfo->score; + } +} + +class lesson_add_page_form_essay extends lesson_add_page_form_base { + + public $qtype = 'essay'; + public $qtypestring = 'essay'; + + public function custom_definition() { + + $this->add_jumpto(0); + $this->add_score(0, null, 1); + + } +} + +class lesson_display_answer_form_essay extends moodleform { + + public function definition() { + global $USER, $OUTPUT; + $mform = $this->_form; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $mform->addElement('editor', 'answer', get_string('youranswer', 'lesson'), null, null); + $mform->setType('answer', PARAM_CLEANHTML); + + $this->add_action_buttons(null, get_string("pleaseenteryouranswerinthebox", "lesson")); + } + +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/matching.php b/mod/lesson/pagetypes/matching.php new file mode 100644 index 0000000000..032114c331 --- /dev/null +++ b/mod/lesson/pagetypes/matching.php @@ -0,0 +1,513 @@ +. + +/** + * Matching + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** Matching question type */ +define("LESSON_PAGE_MATCHING", "5"); + +class lesson_page_type_matching extends lesson_page { + + protected $type = lesson_page::TYPE_QUESTION; + protected $typeid = LESSON_PAGE_MATCHING; + protected $typeidstring = 'matching'; + protected $string = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function display($renderer, $attempt) { + global $USER, $CFG, $PAGE; + $mform = $this->make_answer_form($attempt); + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->pageid = $this->properties->id; + $mform->set_data($data); + return $mform->display(); + } + + protected function make_answer_form($attempt=null) { + global $USER, $CFG; + // don't suffle answers (could be an option??) + $answers = array_slice($this->get_answers(), 2); + $responses = array(); + foreach ($answers as $answer) { + // get all the response + if ($answer->response != NULL) { + $responses[] = trim($answer->response); + } + } + + $responseoptions = array(); + if (!empty($responses)) { + shuffle($responses); + $responses = array_unique($responses); + foreach ($responses as $response) { + $responseoptions[htmlspecialchars(trim($response))] = $response; + } + } + if (isset($USER->modattempts[$this->lesson->id]) && !empty($attempt->useranswer)) { + $useranswers = explode(',', $attempt->useranswer); + $t = 0; + } else { + $useranswers = array(); + } + + $action = $CFG->wwwroot.'/mod/lesson/continue.php'; + $params = array('answers'=>$answers, 'useranswers'=>$useranswers, 'responseoptions'=>$responseoptions, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); + $mform = new lesson_display_answer_form_matching($action, $params); + return $mform; + } + + public function create_answers($properties) { + global $DB; + // now add the answers + $newanswer = new stdClass; + $newanswer->lessonid = $this->lesson->id; + $newanswer->pageid = $this->properties->id; + $newanswer->timecreated = $this->properties->timecreated; + + $answers = array(); + + // need to add two to offset correct response and wrong response + $this->lesson->maxanswers = $this->lesson->maxanswers + 2; + for ($i = 0; $i < $this->lesson->maxanswers; $i++) { + $answer = clone($newanswer); + if (!empty($properties->answer[$i])) { + $answer->answer = format_text($properties->answer[$i], FORMAT_PLAIN); + if (isset($properties->response[$i])) { + $answer->response = format_text($properties->response[$i], FORMAT_PLAIN); + } + if (isset($properties->jumpto[$i])) { + $answer->jumpto = $properties->jumpto[$i]; + } + if ($this->lesson->custom && isset($properties->score[$i])) { + $answer->score = $properties->score[$i]; + } + $answer->id = $DB->insert_record("lesson_answers", $answer); + $answers[$answer->id] = new lesson_page_answer($answer); + } else if ($i < 2) { + $answer->id = $DB->insert_record("lesson_answers", $answer); + $answers[$answer->id] = new lesson_page_answer($answer); + } else { + break; + } + } + $this->answers = $answers; + return $answers; + } + + public function check_answer() { + global $CFG; + $result = parent::check_answer(); + + $mform = $this->make_answer_form(); + + $data = $mform->get_data(); + require_sesskey(); + + if (!$data) { + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$this->properties->id))); + } + + $response = $data->response; + if (!is_array($response)) { + $result->noanswer = true; + return $result; + } + $answers = $this->get_answers(); + + $ncorrect = 0; + $i = 0; + foreach ($answers as $answer) { + if ($i < 2) { + // ignore first two answers, they are correct response + // and wrong response + $i++; + continue; + } + if ($answer->response == $response[$answer->id]) { + $ncorrect++; + } + if ($i == 2) { + $correctpageid = $answer->jumpto; + $correctanswerid = $answer->id; + } + if ($i == 3) { + $wrongpageid = $answer->jumpto; + $wronganswerid = $answer->id; + } + $i++; + } + // get he users exact responses for record keeping + $userresponse = array(); + foreach ($response as $key => $value) { + foreach($answers as $answer) { + if ($value == $answer->response) { + $userresponse[] = $answer->id; + } + if ((int)$answer->id === (int)$key) { + $result->studentanswer .= '
      '.$answer->answer.' = '.$value; + } + } + } + $result->userresponse = implode(",", $userresponse); + + if ($ncorrect == count($answers)-2) { // dont count correct/wrong responses in the total. + foreach ($answers as $answer) { + if ($answer->response == NULL && $answer->answer != NULL) { + $result->response = $answer->answer; + break; + } + } + if (isset($correctpageid)) { + $result->newpageid = $correctpageid; + } + if (isset($correctanswerid)) { + $result->answerid = $correctanswerid; + } + $result->correctanswer = true; + } else { + $t = 0; + foreach ($answers as $answer) { + if ($answer->response == NULL && $answer->answer != NULL) { + if ($t == 1) { + $result->response = $answer->answer; + break; + } + $t++; + } + } + if (isset($wrongpageid)) { + $result->newpageid = $wrongpageid; + } + if (isset($wronganswerid)) { + $result->answerid = $wronganswerid; + } + } + return $result; + } + + public function option_description_string() { + return get_string("firstanswershould", "lesson"); + } + + public function display_answers(html_table $table) { + $answers = $this->get_answers(); + $options = new stdClass; + $options->noclean = true; + $options->para = false; + $i = 1; + $n = 0; + + foreach ($answers as $answer) { + if ($n < 2) { + if ($answer->answer != NULL) { + $cells = array(); + if ($n == 0) { + $cells[] = "".get_string("correctresponse", "lesson").''; + } else { + $cells[] = "".get_string("wrongresponse", "lesson").''; + } + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + } + $n++; + $i--; + } else { + $cells = array(); + if ($this->lesson->custom && $answer->score > 0) { + // if the score is > 0, then it is correct + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->custom) { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = ''.get_string("matchesanswer", "lesson")." $i: "; + $cells[] = format_text($answer->response, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + } + + if ($i == 1) { + $cells = array(); + $cells[] = ''.get_string("correctanswerscore", "lesson")." $i: "; + $cells[] = $answer->score; + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = ''.get_string("correctanswerjump", "lesson")." $i: "; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + } elseif ($i == 2) { + $cells = array(); + $cells[] = ''.get_string("wronganswerscore", "lesson")." $i: "; + $cells[] = $answer->score; + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = ''.get_string("wronganswerjump", "lesson")." $i: "; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + } + + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + + $i++; + } + return $table; + } + public function update($properties) { + global $DB, $PAGE; + $answers = $this->get_answers(); + $properties->id = $this->properties->id; + $properties->lessonid = $this->lesson->id; + $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes), get_context_instance(CONTEXT_MODULE, $PAGE->cm->id), 'lesson_page_contents', $properties->id); + $DB->update_record("lesson_pages", $properties); + + // need to add two to offset correct response and wrong response + $this->lesson->maxanswers += 2; + for ($i = 0; $i < $this->lesson->maxanswers; $i++) { + if (!array_key_exists($i, $this->answers)) { + $this->answers[$i] = new stdClass; + $this->answers[$i]->lessonid = $this->lesson->id; + $this->answers[$i]->pageid = $this->id; + $this->answers[$i]->timecreated = $this->timecreated; + } + if (!empty($properties->answer[$i])) { + $this->answers[$i]->answer = format_text($properties->answer[$i], FORMAT_PLAIN); + if (isset($properties->response[$i])) { + $this->answers[$i]->response = format_text($properties->response[$i], FORMAT_PLAIN); + } + if (isset($properties->jumpto[$i])) { + $this->answers[$i]->jumpto = $properties->jumpto[$i]; + } + if ($this->lesson->custom && isset($properties->score[$i])) { + $this->answers[$i]->score = $properties->score[$i]; + } + if (!isset($this->answers[$i]->id)) { + $this->answers[$i]->id = $DB->insert_record("lesson_answers", $this->answers[$i]); + } else { + $DB->update_record("lesson_answers", $this->answers[$i]->properties()); + } + + } else if ($i < 2) { + if (!isset($this->answers[$i]->id)) { + $this->answers[$i]->id = $DB->insert_record("lesson_answers", $this->answers[$i]); + } else { + $DB->update_record("lesson_answers", $this->answers[$i]->properties()); + } + + } else { + break; + } + } + return true; + } + public function stats(array &$pagestats, $tries) { + if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt + $temp = $tries[$this->lesson->maxattempts - 1]; + } else { + // else, user attempted the question less than the max, so grab the last one + $temp = end($tries); + } + if ($temp->correct) { + if (isset($pagestats[$temp->pageid]["correct"])) { + $pagestats[$temp->pageid]["correct"]++; + } else { + $pagestats[$temp->pageid]["correct"] = 1; + } + } + if (isset($pagestats[$temp->pageid]["total"])) { + $pagestats[$temp->pageid]["total"]++; + } else { + $pagestats[$temp->pageid]["total"] = 1; + } + return true; + } + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = array(); + foreach ($this->get_answers() as $answer) { + $answers[$answer->id] = $answer; + } + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + if ($n == 0 && $useranswer != NULL && $useranswer->correct) { + if ($answer->response == NULL && $useranswer != NULL) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = $answer->response; + } + } elseif ($n == 1 && $useranswer != NULL && !$useranswer->correct) { + if ($answer->response == NULL && $useranswer != NULL) { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } else { + $answerdata->response = $answer->response; + } + } elseif ($n > 1) { + if ($n == 2 && $useranswer != NULL && $useranswer->correct) { + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } else { + $answerdata->score = get_string("receivedcredit", "lesson"); + } + } elseif ($n == 3 && $useranswer != NULL && !$useranswer->correct) { + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } + $data = ""; + if ($useranswer != NULL) { + $userresponse = explode(",", $useranswer->useranswer); + $data .= ""; + } else { + $data .= ""; + } + + if ($n == 2) { + if (isset($pagestats[$this->properties->id])) { + if (!array_key_exists('correct', $pagestats[$this->properties->id])) { + $pagestats[$this->properties->id]["correct"] = 0; + } + $percent = $pagestats[$this->properties->id]["correct"] / $pagestats[$this->properties->id]["total"] * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("answeredcorrectly", "lesson"); + } else { + $percent = get_string("nooneansweredthisquestion", "lesson"); + } + } else { + $percent = ""; + } + + $answerdata->answers[] = array($data, $percent); + $i++; + } + $n++; + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } + public function get_jumps() { + global $DB; + // The jumps for matching question type is stored + // in the 3rd and 4rth answer record. + $jumps = array(); + $params = array ("lessonid" => $this->lesson->id, "pageid" => $this->properties->id); + if ($answers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid and pageid = :pageid", $params, 'id', '*', '2', '2')) { + foreach ($answers as $answer) { + $jumps[] = $this->get_jump_name($answer->jumpto); + } + } + return $jumps; + } +} + +class lesson_add_page_form_matching extends lesson_add_page_form_base { + + public $qtype = 'matching'; + public $qtypestring = 'matching'; + + public function custom_definition() { + + $this->_form->addElement('header', 'correctresponse', get_string('correctresponse', 'lesson')); + $this->add_textarea('answer', 0, get_string('correctresponse', 'lesson')); + $this->add_jumpto(2, get_string('correctanswerjump','lesson')); + $this->add_score(2, get_string("correctanswerscore", "lesson")); + + $this->_form->addElement('header', 'wrongresponse', get_string('wrongresponse', 'lesson')); + $this->add_textarea('answer', 1, get_string('wrongresponse', 'lesson')); + $this->add_jumpto(3, get_string('wronganswerjump','lesson')); + $this->add_score(3, get_string("wronganswerscore", "lesson")); + + for ($i = 2; $i < $this->_customdata['lesson']->maxanswers+2; $i++) { + $this->_form->addElement('header', 'matchingpair'.($i-1), get_string('matchingpair', 'lesson', $i-1)); + $this->add_answer($i); + $this->add_response($i, get_string('matchesanswer','lesson')); + } + } +} + + +class lesson_display_answer_form_matching extends moodleform { + + public function definition() { + global $USER, $OUTPUT; + $mform = $this->_form; + $answers = $this->_customdata['answers']; + $useranswers = $this->_customdata['useranswers']; + $responseoptions = $this->_customdata['responseoptions']; + $lessonid = $this->_customdata['lessonid']; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $i = 0; + foreach ($answers as $answer) { + $mform->addElement('html', '
      '); + if ($answer->response != NULL) { + $mform->addElement('select', 'response['.$answer->id.']', format_text($answer->answer,FORMAT_MOODLE,$options), $responseoptions); + $mform->setType('response['.$answer->id.']', PARAM_TEXT); + if (isset($USER->modattempts[$lessonid])) { + $mform->setDefault('response['.$answer->id.']', htmlspecialchars(trim($answers[$useranswers[$t]]->response))); + } else { + $mform->setDefault('response['.$answer->id.']', 'answeroption'); + } + } + $mform->addElement('html', '
      '); + $i++; + } + + $this->add_action_buttons(null, get_string("pleasematchtheabovepairs", "lesson")); + } + +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/multichoice.php b/mod/lesson/pagetypes/multichoice.php new file mode 100644 index 0000000000..76499e0ec4 --- /dev/null +++ b/mod/lesson/pagetypes/multichoice.php @@ -0,0 +1,503 @@ +. + +/** + * Multichoice + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** Multichoice question type */ +define("LESSON_PAGE_MULTICHOICE", "3"); + +class lesson_page_type_multichoice extends lesson_page { + + protected $type = lesson_page::TYPE_QUESTION; + protected $typeidstring = 'multichoice'; + protected $typeid = LESSON_PAGE_MULTICHOICE; + protected $string = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + + public function display($renderer, $attempt) { + global $CFG, $PAGE; + $answers = $this->get_answers(); + shuffle($answers); + $action = $CFG->wwwroot.'/mod/lesson/continue.php'; + $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); + if ($this->properties->qoption) { + $mform = new lesson_display_answer_form_multichoice_multianswer($action, $params); + } else { + $mform = new lesson_display_answer_form_multichoice_singleanswer($action, $params); + } + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->pageid = $this->properties->id; + $mform->set_data($data); + return $mform->display(); + } + + public function check_answer() { + global $DB, $CFG; + $result = parent::check_answer(); + + $answers = $this->get_answers(); + shuffle($answers); + $action = $CFG->wwwroot.'/mod/lesson/continue.php'; + $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); + if ($this->properties->qoption) { + $mform = new lesson_display_answer_form_multichoice_multianswer($action, $params); + } else { + $mform = new lesson_display_answer_form_multichoice_singleanswer($action, $params); + } + $data = $mform->get_data(); + require_sesskey(); + + if (!$data) { + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$this->properties->id))); + } + + if ($this->properties->qoption) { + // MULTIANSWER allowed, user's answer is an array + + if (empty($data->answer) || !is_array($data->answer)) { + $result->noanswer = true; + return $result; + } + + $studentanswers = $data->answer; + foreach ($studentanswers as $key => $useranswer) { + $studentanswers[$key] = clean_param($useranswer, PARAM_INT); + } + + // get what the user answered + $result->userresponse = implode(",", $studentanswers); + + // get the answers in a set order, the id order + $answers = $this->get_answers(); + $ncorrect = 0; + $nhits = 0; + $correctresponse = ''; + $wrongresponse = ''; + $correctanswerid = 0; + $wronganswerid = 0; + // store student's answers for displaying on feedback page + foreach ($answers as $answer) { + foreach ($studentanswers as $key => $answerid) { + if ($answerid == $answer->id) { + $result->studentanswer .= '
      '.$answer->answer; + } + } + } + // this is for custom scores. If score on answer is positive, it is correct + if ($this->lesson->custom) { + $ncorrect = 0; + $nhits = 0; + foreach ($answers as $answer) { + if ($answer->score > 0) { + $ncorrect++; + + foreach ($studentanswers as $key => $answerid) { + if ($answerid == $answer->id) { + $nhits++; + } + } + // save the first jumpto page id, may be needed!... + if (!isset($correctpageid)) { + // leave in its "raw" state - will converted into a proper page id later + $correctpageid = $answer->jumpto; + } + // save the answer id for scoring + if ($correctanswerid == 0) { + $correctanswerid = $answer->id; + } + // ...also save any response from the correct answers... + if (trim(strip_tags($answer->response))) { + $correctresponse = $answer->response; + } + } else { + // save the first jumpto page id, may be needed!... + if (!isset($wrongpageid)) { + // leave in its "raw" state - will converted into a proper page id later + $wrongpageid = $answer->jumpto; + } + // save the answer id for scoring + if ($wronganswerid == 0) { + $wronganswerid = $answer->id; + } + // ...and from the incorrect ones, don't know which to use at this stage + if (trim(strip_tags($answer->response))) { + $wrongresponse = $answer->response; + } + } + } + } else { + foreach ($answers as $answer) { + if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + $ncorrect++; + foreach ($studentanswers as $key => $answerid) { + if ($answerid == $answer->id) { + $nhits++; + } + } + // save the first jumpto page id, may be needed!... + if (!isset($correctpageid)) { + // leave in its "raw" state - will converted into a proper page id later + $correctpageid = $answer->jumpto; + } + // save the answer id for scoring + if ($correctanswerid == 0) { + $correctanswerid = $answer->id; + } + // ...also save any response from the correct answers... + if (trim(strip_tags($answer->response))) { + $correctresponse = $answer->response; + } + } else { + // save the first jumpto page id, may be needed!... + if (!isset($wrongpageid)) { + // leave in its "raw" state - will converted into a proper page id later + $wrongpageid = $answer->jumpto; + } + // save the answer id for scoring + if ($wronganswerid == 0) { + $wronganswerid = $answer->id; + } + // ...and from the incorrect ones, don't know which to use at this stage + if (trim(strip_tags($answer->response))) { + $wrongresponse = $answer->response; + } + } + } + } + if ((count($studentanswers) == $ncorrect) and ($nhits == $ncorrect)) { + $result->correctanswer = true; + $result->response = $correctresponse; + $result->newpageid = $correctpageid; + $result->answerid = $correctanswerid; + } else { + $result->response = $wrongresponse; + $result->newpageid = $wrongpageid; + $result->answerid = $wronganswerid; + } + } else { + // only one answer allowed + + if (empty($data->answerid) && !is_int($data->answerid)) { + $result->noanswer = true; + return $result; + } + $result->answerid = $data->answerid; + if (!$answer = $DB->get_record("lesson_answers", array("id" => $result->answerid))) { + print_error("Continue: answer record not found"); + } + if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + $result->correctanswer = true; + } + if ($this->lesson->custom) { + if ($answer->score > 0) { + $result->correctanswer = true; + } else { + $result->correctanswer = false; + } + } + $result->newpageid = $answer->jumpto; + $result->response = trim($answer->response); + $result->userresponse = $answer->answer; + } + return $result; + } + + public function option_description_string() { + if ($this->properties->qoption) { + return " - ".get_string("multianswer", "lesson"); + } + return parent::option_description_string(); + } + + public function display_answers(html_table $table) { + $answers = $this->get_answers(); + $options = new stdClass; + $options->noclean = true; + $options->para = false; + $i = 1; + foreach ($answers as $answer) { + $cells = array(); + if ($this->lesson->custom && $answer->score > 0) { + // if the score is > 0, then it is correct + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->custom) { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + // underline correct answers + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("response", "lesson")." $i"; + $cells[] = format_text($answer->response, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("score", "lesson").''; + $cells[] = $answer->score; + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("jump", "lesson").''; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + $i++; + } + return $table; + } + public function stats(array &$pagestats, $tries) { + if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt + $temp = $tries[$this->lesson->maxattempts - 1]; + } else { + // else, user attempted the question less than the max, so grab the last one + $temp = end($tries); + } + if ($this->properties->qoption) { + $userresponse = explode(",", $temp->useranswer); + foreach ($userresponse as $response) { + if (isset($pagestats[$temp->pageid][$response])) { + $pagestats[$temp->pageid][$response]++; + } else { + $pagestats[$temp->pageid][$response] = 1; + } + } + } else { + if (isset($pagestats[$temp->pageid][$temp->answerid])) { + $pagestats[$temp->pageid][$temp->answerid]++; + } else { + $pagestats[$temp->pageid][$temp->answerid] = 1; + } + } + if (isset($pagestats[$temp->pageid]["total"])) { + $pagestats[$temp->pageid]["total"]++; + } else { + $pagestats[$temp->pageid]["total"] = 1; + } + return true; + } + + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + if ($this->properties->qoption) { + if ($useranswer == NULL) { + $userresponse = array(); + } else { + $userresponse = explode(",", $useranswer->useranswer); + } + if (in_array($answer->id, $userresponse)) { + // make checked + $data = ""; + if (!isset($answerdata->response)) { + if ($answer->response == NULL) { + if ($useranswer->correct) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } + } else { + $answerdata->response = $answer->response; + } + } + if (!isset($answerdata->score)) { + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } elseif ($useranswer->correct) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } + } else { + // unchecked + $data = ""; + } + if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { + $data = "
      ".$data.' '.format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."
      "; + } else { + $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions); + } + } else { + if ($useranswer != NULL and $answer->id == $useranswer->answerid) { + // make checked + $data = ""; + if ($answer->response == NULL) { + if ($useranswer->correct) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } + } else { + $answerdata->response = $answer->response; + } + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } elseif ($useranswer->correct) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } else { + // unchecked + $data = ""; + } + if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { + $data = "
      ".$data.' '.format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."
      "; + } else { + $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions); + } + } + if (isset($pagestats[$this->properties->id][$answer->id])) { + $percent = $pagestats[$this->properties->id][$answer->id] / $pagestats[$this->properties->id]["total"] * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("checkedthisone", "lesson"); + } else { + $percent = get_string("noonecheckedthis", "lesson"); + } + + $answerdata->answers[] = array($data, $percent); + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } +} + + +class lesson_add_page_form_multichoice extends lesson_add_page_form_base { + + public $qtype = 'multichoice'; + public $qtypestring = 'multichoice'; + + public function custom_definition() { + + $this->_form->addElement('checkbox', 'qoption', get_string('options', 'lesson'), get_string('multianswer', 'lesson')); + $this->_form->setDefault('qoption', true); + $this->_form->setHelpButton('qoption', array("questionoption", get_string("questionoption", "lesson"), "lesson")); + + for ($i = 0; $i < $this->_customdata['lesson']->maxanswers; $i++) { + $this->_form->addElement('header', 'answertitle'.$i, get_string('answer').' '.($i+1)); + $this->add_answer($i); + $this->add_response($i); + $this->add_jumpto($i); + $this->add_score($i, null, ($i===0)?1:0); + } + } +} + +class lesson_display_answer_form_multichoice_singleanswer extends moodleform { + + public function definition() { + global $USER, $OUTPUT; + $mform = $this->_form; + $answers = $this->_customdata['answers']; + $lessonid = $this->_customdata['lessonid']; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $i = 0; + foreach ($answers as $answer) { + $mform->addElement('html', '
      '); + $mform->addElement('radio','answerid',null,format_text(trim($answer->answer), FORMAT_MOODLE, $options),$answer->id); + $mform->setType('answer'.$i, PARAM_INT); + if (isset($USER->modattempts[$lessonid]) && $answer->id == $attempt->answerid) { + $mform->setDefault('answerid', true); + } + $mform->addElement('html', '
      '); + $i++; + } + + $this->add_action_buttons(null, get_string("pleasecheckoneanswer", "lesson")); + } + +} + +class lesson_display_answer_form_multichoice_multianswer extends moodleform { + + public function definition() { + global $USER, $OUTPUT; + $mform = $this->_form; + $answers = $this->_customdata['answers']; + $lessonid = $this->_customdata['lessonid']; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $i = 0; + foreach ($answers as $answer) { + $mform->addElement('html', '
      '); + $mform->addElement('checkbox','answer['.$i.']',null,format_text(trim($answer->answer), FORMAT_MOODLE, $options),$answer->id); + $mform->setType('answer'.$i, PARAM_INT); + if (isset($USER->modattempts[$lessonid]) && $answer->id == $attempt->answerid) { + $mform->setDefault('answer['.$i.']', true); + } + $mform->addElement('html', '
      '); + $i++; + } + + $this->add_action_buttons(null, get_string("pleasecheckoneormoreanswers", "lesson")); + } + +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/numerical.php b/mod/lesson/pagetypes/numerical.php new file mode 100644 index 0000000000..43c1aee1b8 --- /dev/null +++ b/mod/lesson/pagetypes/numerical.php @@ -0,0 +1,282 @@ +. + +/** + * Numerical + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** Numerical question type */ +define("LESSON_PAGE_NUMERICAL", "8"); + +class lesson_page_type_numerical extends lesson_page { + + protected $type = lesson_page::TYPE_QUESTION; + protected $typeidstring = 'numerical'; + protected $typeid = LESSON_PAGE_NUMERICAL; + protected $string = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function display($renderer, $attempt) { + global $USER, $CFG, $PAGE; + $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->pageid = $this->properties->id; + if (isset($USER->modattempts[$this->lesson->id])) { + $data->answer = s($attempt->useranswer); + } + $mform->set_data($data); + return $mform->display(); + } + public function check_answer() { + global $CFG; + $result = parent::check_answer(); + + $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); + $data = $mform->get_data(); + require_sesskey(); + + // set defaults + $result->response = ''; + $result->newpageid = 0; + + if (isset($data->answer)) { + // just doing default PARAM_RAW, not doing PARAM_INT because it could be a float + $result->useranswer = (float)$data->answer; + } else { + $result->noanswer = true; + return $result; + } + $result->studentanswer = $result->userresponse = $result->useranswer; + $answers = $this->get_answers(); + foreach ($answers as $answer) { + if (strpos($answer->answer, ':')) { + // there's a pairs of values + list($min, $max) = explode(':', $answer->answer); + $minimum = (float) $min; + $maximum = (float) $max; + } else { + // there's only one value + $minimum = (float) $answer->answer; + $maximum = $minimum; + } + if (($result->useranswer >= $minimum) && ($result->useranswer <= $maximum)) { + $result->newpageid = $answer->jumpto; + $result->response = trim($answer->response); + if ($this->lesson->jumpto_is_correct($this->properties->id, $result->newpageid)) { + $result->correctanswer = true; + } + if ($this->lesson->custom) { + if ($answer->score > 0) { + $result->correctanswer = true; + } else { + $result->correctanswer = false; + } + } + $result->answerid = $answer->id; + return $result; + } + } + return $result; + } + + public function display_answers(html_table $table) { + $answers = $this->get_answers(); + $options = new stdClass; + $options->noclean = true; + $options->para = false; + $i = 1; + foreach ($answers as $answer) { + $cells = array(); + if ($this->lesson->custom && $answer->score > 0) { + // if the score is > 0, then it is correct + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->custom) { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + // underline correct answers + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("response", "lesson")." $i"; + $cells[] = format_text($answer->response, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("score", "lesson").''; + $cells[] = $answer->score; + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("jump", "lesson").''; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + $i++; + } + return $table; + } + public function stats(array &$pagestats, $tries) { + if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt + $temp = $tries[$this->lesson->maxattempts - 1]; + } else { + // else, user attempted the question less than the max, so grab the last one + $temp = end($tries); + } + if (isset($pagestats[$temp->pageid][$temp->useranswer])) { + $pagestats[$temp->pageid][$temp->useranswer]++; + } else { + $pagestats[$temp->pageid][$temp->useranswer] = 1; + } + if (isset($pagestats[$temp->pageid]["total"])) { + $pagestats[$temp->pageid]["total"]++; + } else { + $pagestats[$temp->pageid]["total"] = 1; + } + return true; + } + + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + if ($useranswer == null && $i == 0) { + // I have the $i == 0 because it is easier to blast through it all at once. + if (isset($pagestats[$this->properties->id])) { + $stats = $pagestats[$this->properties->id]; + $total = $stats["total"]; + unset($stats["total"]); + foreach ($stats as $valentered => $ntimes) { + $data = ''; + $percent = $ntimes / $total * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("enteredthis", "lesson"); + $answerdata->answers[] = array($data, $percent); + } + } else { + $answerdata->answers[] = array(get_string("nooneansweredthisquestion", "lesson"), " "); + } + $i++; + } else if ($useranswer != null && ($answer->id == $useranswer->answerid || ($answer == end($answers) && empty($answerdata)))) { + // get in here when what the user entered is not one of the answers + $data = ''; + if (isset($pagestats[$this->properties->id][$useranswer->useranswer])) { + $percent = $pagestats[$this->properties->id][$useranswer->useranswer] / $pagestats[$this->properties->id]["total"] * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("enteredthis", "lesson"); + } else { + $percent = get_string("nooneenteredthis", "lesson"); + } + $answerdata->answers[] = array($data, $percent); + + if ($answer->id == $useranswer->answerid) { + if ($answer->response == NULL) { + if ($useranswer->correct) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } + } else { + $answerdata->response = $answer->response; + } + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } elseif ($useranswer->correct) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": 0"; + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } + } + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } +} + +class lesson_add_page_form_numerical extends lesson_add_page_form_base { + + public $qtype = 'numerical'; + public $qtypestring = 'numerical'; + + public function custom_definition() { + for ($i = 0; $i < $this->_customdata['lesson']->maxanswers; $i++) { + $this->_form->addElement('header', 'answertitle'.$i, get_string('answer').' '.($i+1)); + $this->add_answer($i); + $this->add_response($i); + $this->add_jumpto($i); + $this->add_score($i, null, ($i===0)?1:0); + } + } +} + +class lesson_display_answer_form_numerical extends moodleform { + + public function definition() { + global $USER, $OUTPUT; + $mform = $this->_form; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $mform->addElement('text', 'answer', get_string('youranswer', 'lesson'), array('size'=>'50', 'maxlength'=>'200')); + $mform->setType('answer', PARAM_FLOAT); + + $this->add_action_buttons(null, get_string("pleaseenteryouranswerinthebox", "lesson")); + } + +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/shortanswer.php b/mod/lesson/pagetypes/shortanswer.php new file mode 100644 index 0000000000..79f8a645ee --- /dev/null +++ b/mod/lesson/pagetypes/shortanswer.php @@ -0,0 +1,349 @@ +. + +/** + * Short answer + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** Short answer question type */ +define("LESSON_PAGE_SHORTANSWER", "1"); + +class lesson_page_type_shortanswer extends lesson_page { + + protected $type = lesson_page::TYPE_QUESTION; + protected $typeidstring = 'shortanswer'; + protected $typeid = LESSON_PAGE_SHORTANSWER; + protected $string = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function display($renderer, $attempt) { + global $USER, $CFG, $PAGE; + $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->pageid = $this->properties->id; + if (isset($USER->modattempts[$this->lesson->id])) { + $data->answer = s($attempt->useranswer); + } + $mform->set_data($data); + return $mform->display(); + } + public function check_answer() { + global $CFG; + $result = parent::check_answer(); + + $mform = new lesson_display_answer_form_shortanswer($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents())); + $data = $mform->get_data(); + require_sesskey(); + + $studentanswer = trim($data->answer); + if ($studentanswer === '') { + $result->noanswer = true; + return $result; + } + $studentanswer = s($studentanswer); + + $i=0; + $answers = $this->get_answers(); + foreach ($answers as $answer) { + $i++; + $expectedanswer = $answer->answer; // for easier handling of $answer->answer + $ismatch = false; + $markit = false; + $useregexp = ($this->qoption); + + if ($useregexp) { //we are using 'normal analysis', which ignores case + $ignorecase = ''; + if (substr($expectedanswer,0,-2) == '/i') { + $expectedanswer = substr($expectedanswer,0,-2); + $ignorecase = 'i'; + } + } else { + $expectedanswer = str_replace('*', '#####', $expectedanswer); + $expectedanswer = preg_quote($expectedanswer, '/'); + $expectedanswer = str_replace('#####', '.*', $expectedanswer); + } + // see if user typed in any of the correct answers + if ((!$this->lesson->custom && $this->lesson->jumpto_is_correct($pageid, $answer->jumpto)) or ($this->lesson->custom && $answer->score > 0) ) { + if (!$useregexp) { // we are using 'normal analysis', which ignores case + if (preg_match('/^'.$expectedanswer.'$/i',$studentanswer)) { + $ismatch = true; + } + } else { + if (preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$studentanswer)) { + $ismatch = true; + } + } + if ($ismatch == true) { + $result->correctanswer = true; + } + } else { + if (!$useregexp) { //we are using 'normal analysis' + // see if user typed in any of the wrong answers; don't worry about case + if (preg_match('/^'.$expectedanswer.'$/i',$studentanswer)) { + $ismatch = true; + } + } else { // we are using regular expressions analysis + $startcode = substr($expectedanswer,0,2); + switch ($startcode){ + //1- check for absence of required string in $studentanswer (coded by initial '--') + case "--": + $expectedanswer = substr($expectedanswer,2); + if (!preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$studentanswer)) { + $ismatch = true; + } + break; + //2- check for code for marking wrong strings (coded by initial '++') + case "++": + $expectedanswer=substr($expectedanswer,2); + $markit = true; + //check for one or several matches + if (preg_match_all('/'.$expectedanswer.'/'.$ignorecase,$studentanswer, $matches)) { + $ismatch = true; + $nb = count($matches[0]); + $original = array(); + $marked = array(); + $fontStart = ''; + $fontEnd = ''; + for ($i = 0; $i < $nb; $i++) { + array_push($original,$matches[0][$i]); + array_push($marked,$fontStart.$matches[0][$i].$fontEnd); + } + $studentanswer = str_replace($original, $marked, $studentanswer); + } + break; + //3- check for wrong answers belonging neither to -- nor to ++ categories + default: + if (preg_match('/^'.$expectedanswer.'$/'.$ignorecase,$studentanswer, $matches)) { + $ismatch = true; + } + break; + } + $result->correctanswer = false; + } + } + if ($ismatch) { + $result->newpageid = $answer->jumpto; + if (trim(strip_tags($answer->response))) { + $result->response = $answer->response; + } + $result->answerid = $answer->id; + break; // quit answer analysis immediately after a match has been found + } + } + $result->studentanswer = $result->userresponse = $studentanswer; + return $result; + } + + public function option_description_string() { + if ($this->properties->qoption) { + return " - ".get_string("casesensitive", "lesson"); + } + return parent::option_description_string(); + } + + public function display_answers(html_table $table) { + $answers = $this->get_answers(); + $options = new stdClass; + $options->noclean = true; + $options->para = false; + $i = 1; + foreach ($answers as $answer) { + $cells = array(); + if ($this->lesson->custom && $answer->score > 0) { + // if the score is > 0, then it is correct + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->custom) { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + // underline correct answers + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("response", "lesson")." $i"; + $cells[] = format_text($answer->response, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("score", "lesson").''; + $cells[] = $answer->score; + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("jump", "lesson").''; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + $i++; + } + return $table; + } + public function stats(array &$pagestats, $tries) { + if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt + $temp = $tries[$this->lesson->maxattempts - 1]; + } else { + // else, user attempted the question less than the max, so grab the last one + $temp = end($tries); + } + if (isset($pagestats[$temp->pageid][$temp->useranswer])) { + $pagestats[$temp->pageid][$temp->useranswer]++; + } else { + $pagestats[$temp->pageid][$temp->useranswer] = 1; + } + if (isset($pagestats[$temp->pageid]["total"])) { + $pagestats[$temp->pageid]["total"]++; + } else { + $pagestats[$temp->pageid]["total"] = 1; + } + return true; + } + + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + if ($useranswer == null && $i == 0) { + // I have the $i == 0 because it is easier to blast through it all at once. + if (isset($pagestats[$this->properties->id])) { + $stats = $pagestats[$this->properties->id]; + $total = $stats["total"]; + unset($stats["total"]); + foreach ($stats as $valentered => $ntimes) { + $data = ''; + $percent = $ntimes / $total * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("enteredthis", "lesson"); + $answerdata->answers[] = array($data, $percent); + } + } else { + $answerdata->answers[] = array(get_string("nooneansweredthisquestion", "lesson"), " "); + } + $i++; + } else if ($useranswer != null && ($answer->id == $useranswer->answerid || ($answer == end($answers) && empty($answerdata)))) { + // get in here when what the user entered is not one of the answers + $data = ''; + if (isset($pagestats[$this->properties->id][$useranswer->useranswer])) { + $percent = $pagestats[$this->properties->id][$useranswer->useranswer] / $pagestats[$this->properties->id]["total"] * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("enteredthis", "lesson"); + } else { + $percent = get_string("nooneenteredthis", "lesson"); + } + $answerdata->answers[] = array($data, $percent); + + if ($answer->id == $useranswer->answerid) { + if ($answer->response == NULL) { + if ($useranswer->correct) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } + } else { + $answerdata->response = $answer->response; + } + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } elseif ($useranswer->correct) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": 0"; + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } + } + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } +} + + +class lesson_add_page_form_shortanswer extends lesson_add_page_form_base { + public $qtype = 'shortanswer'; + public $qtypestring = 'shortanswer'; + + public function custom_definition() { + + $this->_form->addElement('checkbox', 'qoption', get_string('options', 'lesson'), get_string('casesensitive', 'lesson')); + $this->_form->setDefault('qoption', true); + $this->_form->setHelpButton('qoption', array("questionoption", get_string("questionoption", "lesson"), "lesson")); + + for ($i = 0; $i < $this->_customdata['lesson']->maxanswers; $i++) { + $this->_form->addElement('header', 'answertitle'.$i, get_string('answer').' '.($i+1)); + $this->add_answer($i); + $this->add_response($i); + $this->add_jumpto($i); + $this->add_score($i, null, ($i===0)?1:0); + } + } +} + +class lesson_display_answer_form_shortanswer extends moodleform { + + public function definition() { + global $OUTPUT; + $mform = $this->_form; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $mform->addElement('text', 'answer', get_string('youranswer', 'lesson'), array('size'=>'50', 'maxlength'=>'200')); + $mform->setType('answer', PARAM_TEXT); + + $this->add_action_buttons(null, get_string("pleaseenteryouranswerinthebox", "lesson")); + } + +} \ No newline at end of file diff --git a/mod/lesson/pagetypes/truefalse.php b/mod/lesson/pagetypes/truefalse.php new file mode 100644 index 0000000000..4fc5c6736f --- /dev/null +++ b/mod/lesson/pagetypes/truefalse.php @@ -0,0 +1,317 @@ +. + +/** + * True/false + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + + /** True/False question type */ +define("LESSON_PAGE_TRUEFALSE", "2"); + +class lesson_page_type_truefalse extends lesson_page { + + protected $type = lesson_page::TYPE_QUESTION; + protected $typeidstring = 'truefalse'; + protected $typeid = LESSON_PAGE_TRUEFALSE; + protected $string = null; + + public function get_typeid() { + return $this->typeid; + } + public function get_typestring() { + if ($this->string===null) { + $this->string = get_string($this->typeidstring, 'lesson'); + } + return $this->string; + } + public function get_idstring() { + return $this->typeidstring; + } + public function display($renderer, $attempt) { + global $USER, $CFG, $PAGE; + $answers = $this->get_answers(); + shuffle($answers); + + $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); + $mform = new lesson_display_answer_form_truefalse($CFG->wwwroot.'/mod/lesson/continue.php', $params); + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->pageid = $this->properties->id; + $mform->set_data($data); + return $mform->display(); + } + public function check_answer() { + global $DB, $CFG; + $answers = $this->get_answers(); + shuffle($answers); + $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); + $mform = new lesson_display_answer_form_truefalse($CFG->wwwroot.'/mod/lesson/continue.php', $params); + $data = $mform->get_data(); + require_sesskey(); + + $result = parent::check_answer(); + + $answerid = $data->answerid; + if ($answerid === false) { + $result->noanswer = true; + return $result; + } + $result->answerid = $answerid; + if (!$answer = $DB->get_record("lesson_answers", array("id" => $result->answerid))) { + print_error("Continue: answer record not found"); + } + if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + $result->correctanswer = true; + } + if ($this->lesson->custom) { + if ($answer->score > 0) { + $result->correctanswer = true; + } else { + $result->correctanswer = false; + } + } + $result->newpageid = $answer->jumpto; + $result->response = trim($answer->response); + $result->studentanswer = $result->userresponse = $answer->answer; + return $result; + } + + public function display_answers(html_table $table) { + $answers = $this->get_answers(); + $options = new stdClass; + $options->noclean = true; + $options->para = false; + $i = 1; + foreach ($answers as $answer) { + $cells = array(); + if ($this->lesson->custom && $answer->score > 0) { + // if the score is > 0, then it is correct + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->custom) { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { + // underline correct answers + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } else { + $cells[] = ''.get_string("answer", "lesson")." $i: \n"; + } + $cells[] = format_text($answer->answer, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("response", "lesson")." $i"; + $cells[] = format_text($answer->response, FORMAT_MOODLE, $options); + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("score", "lesson").''; + $cells[] = $answer->score; + $table->data[] = html_table_row::make($cells); + + $cells = array(); + $cells[] = "".get_string("jump", "lesson").''; + $cells[] = $this->get_jump_name($answer->jumpto); + $table->data[] = html_table_row::make($cells); + + if ($i === 1){ + $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; + } + + $i++; + } + return $table; + } + public function stats(array &$pagestats, $tries) { + if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt + $temp = $tries[$this->lesson->maxattempts - 1]; + } else { + // else, user attempted the question less than the max, so grab the last one + $temp = end($tries); + } + if ($this->properties->qoption) { + $userresponse = explode(",", $temp->useranswer); + foreach ($userresponse as $response) { + if (isset($pagestats[$temp->pageid][$response])) { + $pagestats[$temp->pageid][$response]++; + } else { + $pagestats[$temp->pageid][$response] = 1; + } + } + } else { + if (isset($pagestats[$temp->pageid][$temp->answerid])) { + $pagestats[$temp->pageid][$temp->answerid]++; + } else { + $pagestats[$temp->pageid][$temp->answerid] = 1; + } + } + if (isset($pagestats[$temp->pageid]["total"])) { + $pagestats[$temp->pageid]["total"]++; + } else { + $pagestats[$temp->pageid]["total"] = 1; + } + return true; + } + + public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { + $answers = $this->get_answers(); + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + foreach ($answers as $answer) { + if ($this->properties->qoption) { + if ($useranswer == NULL) { + $userresponse = array(); + } else { + $userresponse = explode(",", $useranswer->useranswer); + } + if (in_array($answer->id, $userresponse)) { + // make checked + $data = ""; + if (!isset($answerdata->response)) { + if ($answer->response == NULL) { + if ($useranswer->correct) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } + } else { + $answerdata->response = $answer->response; + } + } + if (!isset($answerdata->score)) { + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } elseif ($useranswer->correct) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } + } else { + // unchecked + $data = ""; + } + if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { + $data .= "
      ".format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."
      "; + } else { + $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions); + } + } else { + if ($useranswer != NULL and $answer->id == $useranswer->answerid) { + // make checked + $data = ""; + if ($answer->response == NULL) { + if ($useranswer->correct) { + $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); + } else { + $answerdata->response = get_string("thatsthewronganswer", "lesson"); + } + } else { + $answerdata->response = $answer->response; + } + if ($this->lesson->custom) { + $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; + } elseif ($useranswer->correct) { + $answerdata->score = get_string("receivedcredit", "lesson"); + } else { + $answerdata->score = get_string("didnotreceivecredit", "lesson"); + } + } else { + // unchecked + $data = ""; + } + if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { + $data .= "
      ".format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."
      "; + } else { + $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions); + } + } + if (isset($pagestats[$this->properties->id][$answer->id])) { + $percent = $pagestats[$this->properties->id][$answer->id] / $pagestats[$this->properties->id]["total"] * 100; + $percent = round($percent, 2); + $percent .= "% ".get_string("checkedthisone", "lesson"); + } else { + $percent = get_string("noonecheckedthis", "lesson"); + } + + $answerdata->answers[] = array($data, $percent); + $answerpage->answerdata = $answerdata; + } + return $answerpage; + } +} + +class lesson_add_page_form_truefalse extends lesson_add_page_form_base { + + public $qtype = 'truefalse'; + public $qtypestring = 'truefalse'; + + public function custom_definition() { + $this->_form->addElement('header', 'answertitle0', get_string('correctresponse', 'lesson')); + $this->add_answer(0); + $this->add_response(0); + $this->add_jumpto(0, get_string('correctanswerjump', 'lesson')); + $this->add_score(0, get_string('correctanswerscore', 'lesson'), 1); + + $this->_form->addElement('header', 'answertitle1', get_string('wrongresponse', 'lesson')); + $this->add_answer(1); + $this->add_response(1); + $this->add_jumpto(1, get_string('wronganswerjump', 'lesson')); + $this->add_score(1, get_string('wronganswerscore', 'lesson'), 0); + } +} + +class lesson_display_answer_form_truefalse extends moodleform { + + public function definition() { + global $USER, $OUTPUT; + $mform = $this->_form; + $answers = $this->_customdata['answers']; + $lessonid = $this->_customdata['lessonid']; + $contents = $this->_customdata['contents']; + + $mform->addElement('header', 'pageheader', $OUTPUT->box($contents, 'contents')); + + $options = new stdClass; + $options->para = false; + $options->noclean = true; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $i = 0; + foreach ($answers as $answer) { + $mform->addElement('html', '
      '); + $mform->addElement('radio','answerid',null,format_text(trim($answer->answer), FORMAT_MOODLE, $options),$answer->id); + $mform->setType('answerid', PARAM_INT); + if (isset($USER->modattempts[$lessonid]) && $answer->id == $attempt->answerid) { + $mform->setDefault('answerid', true); + } + $mform->addElement('html', '
      '); + $i++; + } + + $this->add_action_buttons(null, get_string("pleasecheckoneanswer", "lesson")); + } + +} \ No newline at end of file diff --git a/mod/lesson/reformat.php b/mod/lesson/reformat.php index 830629b5fc..4f4ec0ace5 100644 --- a/mod/lesson/reformat.php +++ b/mod/lesson/reformat.php @@ -1,9 +1,26 @@ . + /** * jjg7:8/9/2004 * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ function removedoublecr($filename) { diff --git a/mod/lesson/renderer.php b/mod/lesson/renderer.php new file mode 100644 index 0000000000..55caa980ec --- /dev/null +++ b/mod/lesson/renderer.php @@ -0,0 +1,669 @@ +. + +/** + * Moodle renderer used to display special elements of the lesson module + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +class moodle_mod_lesson_renderer extends moodle_renderer_base { + + /** + * A reference to the current general renderer probably {@see moodle_core_renderer} + * @var moodle_renderer_base + */ + protected $output; + + /** + * Contructor method, calls the parent constructor + * @param moodle_page $page + * @param moodle_renderer_base $output Probably moodle_core_renderer + */ + public function __construct($page, $output) { + parent::__construct($page); + $this->output = $output; + } + + /** + * Magic method used to pass calls otherwise meant for the standard renderer + * to it to ensure we don't go causing unnessecary greif. + * + * @param string $method + * @param array $arguments + * @return mixed + */ + public function __call($method, $arguments) { + if (method_exists($this->output, $method)) { + return call_user_func_array(array($this->output, $method), $arguments); + } else { + throw new coding_exception('Unknown method called against '.__CLASS__.' :: '.$method); + } + } + + /** + * Returns the header for the lesson module + * + * @param lesson $lesson + * @param string $currenttab + * @param bool $extraeditbuttons + * @param int $lessonpageid + * @return string + */ + public function header($lesson, $currenttab = '', $extraeditbuttons = false, $lessonpageid = null) { + global $CFG; + + $activityname = format_string($lesson->name, true, $this->page->course->id); + $title = $this->page->course->shortname.": ".$activityname; + + // Build the buttons + $context = get_context_instance(CONTEXT_MODULE, $this->page->cm->id); + if (has_capability('mod/lesson:edit', $context)) { + $buttons = $this->output->update_module_button($this->page->cm->id, 'lesson'); + if ($extraeditbuttons) { + if ($lessonpageid === null) { + print_error('invalidpageid', 'lesson'); + } + if (!empty($lessonpageid) && $lessonpageid != LESSON_EOL) { + $options = array('id'=>$this->page->cm->id, 'redirect'=>'navigation', 'pageid'=>$lessonpageid); + $buttonform = html_form::make_button($CFG->wwwroot.'/mod/lesson/lesson.php', $options, get_string('editpagecontent', 'lesson')); + $buttons .= $this->output->button($buttonform); + } + $buttons = $this->output->box($buttons, 'edit_buttons'); + } + } else { + $buttons = ' '; + } + + /// Header setup + $this->page->requires->css('mod/lesson/lesson.css'); + $this->page->set_title($title); + $this->page->set_heading($this->page->course->fullname); + $this->page->set_button($buttons); + $output = $this->output->header(); + + if (has_capability('mod/lesson:manage', $context)) { + + $helpicon = new moodle_help_icon(); + $helpicon->text = $activityname; + $helpicon->page = "overview"; + $helpicon->module = "lesson"; + + $output .= $this->output->heading_with_help($helpicon); + + if (!empty($currenttab)) { + ob_start(); + include($CFG->dirroot.'/mod/lesson/tabs.php'); + $output .= ob_get_contents(); + ob_end_clean(); + } + } else { + $output .= $this->output->heading($activityname); + } + + foreach ($lesson->messages as $message) { + $output .= $this->output->notification($message[0], $message[1], $message[2]); + } + + return $output; + } + + /** + * Returns the footer + * @return string + */ + public function footer() { + return $this->output->footer(); + } + + /** + * Returns HTML for a lesson inaccessible message + * + * @param string $message + * @return + */ + public function lesson_inaccessible($message) { + global $CFG; + $output = $this->output->box_start('generalbox boxaligncenter'); + $output .= $this->output->box_start('center'); + $output .= $message; + $output .= $this->output->box(''. get_string('returnto', 'lesson', format_string($this->page->course->fullname, true)) .'', 'lessonbutton standardbutton'); + $output .= $this->output->box_end(); + $output .= $this->output->box_end(); + return $output; + } + + /** + * Returns HTML to prompt the user to log in + * @param lesson $lesson + * @param bool $failedattempt + * @return string + */ + public function login_prompt(lesson $lesson, $failedattempt = false) { + global $CFG; + $output = $this->output->box_start('password-form'); + $output .= $this->output->box_start('generalbox boxaligncenter'); + $output .= '
      '; + $output .= '
      '; + $output .= ''; + if ($failedattempt) { + $output .= $this->output->notification(get_string('loginfail', 'lesson')); + } + $output .= get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name)).'

      '; + $output .= get_string('enterpassword', 'lesson')."

      "; + $output .= ' '; + $output .= "
      "; + $output .= '
      '; + $output .= $this->output->box_end(); + $output .= $this->output->box_end(); + return $output; + } + + /** + * Returns HTML to display dependancy errors + * + * @param object $dependentlesson + * @param array $errors + * @return string + */ + public function dependancy_errors($dependentlesson, $errors) { + $output = $this->output->box_start('generalbox boxaligncenter'); + $output .= get_string('completethefollowingconditions', 'lesson', $dependentlesson->name); + $output .= $this->output->box(implode('
      '.get_string('and', 'lesson').'
      ', $errors),'center'); + $output .= $this->output->box_end(); + return $output; + } + + /** + * Returns HTML to display a message + * @param string $message + * @param html_form $button + * @return string + */ + public function message($message, html_form $button = null) { + $output = $this->output->box_start('generalbox boxaligncenter'); + $output .= $message; + if ($button !== null) { + $output .= $this->output->box($this->output->button($button),'lessonbutton standardbutton'); + } + $output .= $this->output->box_end(); + return $output; + } + + /** + * Returns HTML to display a continue button + * @param lesson $lesson + * @param int $lastpageseen + * @return string + */ + public function continue_links(lesson $lesson, $lastpageseenid) { + global $CFG; + $output = $this->output->box(get_string('youhaveseen','lesson'), 'generalbox boxaligncenter'); + $output .= $this->output->box_start('center'); + + $yeslink = html_link::make(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$this->page->cm->id, 'pageid'=>$lastpageseenid, 'startlastseen'=>'yes')), get_string('yes')); + $output .= $this->output->span($this->output->link($yeslink), 'lessonbutton standardbutton'); + + $nolink = html_link::make(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$this->page->cm->id, 'pageid'=>$lesson->firstpageid, 'startlastseen'=>'no')), get_string('no')); + $output .= $this->output->span($this->output->link($nolink), 'lessonbutton standardbutton'); + + $output .= $this->output->box_end(); + return $output; + } + + /** + * Returns HTML to display a page to the user + * @param lesson $lesson + * @param lesson_page $page + * @param object $attempt + * @return string + */ + public function display_page(lesson $lesson, lesson_page $page, $attempt) { + // We need to buffer here as there is an mforms display call + ob_start(); + echo $page->display($this, $attempt); + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + + /** + * Returns HTML to display a collapsed edit form + * + * @param lesson $lesson + * @param int $pageid + * @return string + */ + public function display_edit_collapsed(lesson $lesson, $pageid) { + global $DB, $CFG; + + $manager = lesson_page_type_manager::get($lesson); + $qtypes = $manager->get_page_type_strings(); + $npages = count($lesson->load_all_pages()); + + $table = new html_table(); + $table->head = array(get_string('pagetitle', 'lesson'), get_string('qtype', 'lesson'), get_string('jumps', 'lesson'), get_string('actions', 'lesson')); + $table->align = array('left', 'left', 'left', 'center'); + $table->wrap = array('', 'nowrap', '', 'nowrap'); + $table->tablealign = 'center'; + $table->cellspacing = 0; + $table->cellpadding = '2px'; + $table->width = '80%'; + $table->data = array(); + + $canedit = has_capability('mod/lesson:edit', get_context_instance(CONTEXT_MODULE, $this->page->cm->id)); + + while ($pageid != 0) { + $page = $lesson->load_page($pageid); + $data = array(); + $data[] = "wwwroot/mod/lesson/edit.php?id=".$this->page->cm->id."&mode=single&pageid=".$page->id."\">".format_string($page->title,true).''; + $data[] = $qtypes[$page->qtype]; + $data[] = implode("
      \n", $page->jumps); + if ($canedit) { + $data[] = $this->page_action_links($page, $npages, true); + } else { + $data[] = ''; + } + $table->data[] = $data; + $pageid = $page->nextpageid; + } + + return $this->output->table($table); + } + + /** + * Returns HTML to display the full edit page + * + * @param lesson $lesson + * @param int $pageid + * @param int $prevpageid + * @param bool $single + * @return string + */ + public function display_edit_full(lesson $lesson, $pageid, $prevpageid, $single=false) { + global $DB, $CFG; + + $manager = lesson_page_type_manager::get($lesson); + $qtypes = $manager->get_page_type_strings(); + $npages = count($lesson->load_all_pages()); + $canedit = has_capability('mod/lesson:edit', get_context_instance(CONTEXT_MODULE, $this->page->cm->id)); + + $content = ''; + if ($canedit) { + $content = $this->add_page_links($lesson, $prevpageid); + } + + $options = new stdClass; + $options->noclean = true; + + while ($pageid != 0 && $single!=='stop') { + $page = $lesson->load_page($pageid); + + $pagetable = new html_table(); + $pagetable->align = array('right','left'); + $pagetable->width = '100%'; + $pagetable->tablealign = 'center'; + $pagetable->cellspacing = 0; + $pagetable->cellpadding = '5px'; + $pagetable->data = array(); + + $pageheading = new html_table_cell(); + + $pageheading->text = format_string($page->title); + if ($canedit) { + $pageheading->text .= ' '.$this->page_action_links($page, $npages); + } + $pageheading->style = 'text-align:center'; + $pageheading->colspan = 2; + $pageheading->scope = 'col'; + $pagetable->head = array($pageheading); + + $cell = new html_table_cell(); + $cell->colspan = 2; + $cell->style = 'text-align:center'; + $cell->text = format_text($page->contents, FORMAT_MOODLE, $options); + $pagetable->data[] = html_table_row::make(array($cell)); + + $cell = new html_table_cell(); + $cell->colspan = 2; + $cell->style = 'text-align:center'; + $cell->text = ''.$qtypes[$page->qtype] . $page->option_description_string().''; + $pagetable->data[] = html_table_row::make(array($cell)); + + $pagetable = $page->display_answers($pagetable); + + $content .= $this->output->table($pagetable); + + if ($canedit) { + $content .= $this->add_page_links($lesson, $pageid); + } + + // check the prev links - fix (silently) if necessary - there was a bug in + // versions 1 and 2 when add new pages. Not serious then as the backwards + // links were not used in those versions + if ($page->prevpageid != $prevpageid) { + // fix it + $DB->set_field("lesson_pages", "prevpageid", $prevpageid, array("id" => $page->id)); + debugging("

      ***prevpageid of page $page->id set to $prevpageid***"); + } + + $prevpageid = $page->id; + $pageid = $page->nextpageid; + + if ($single === true) { + $single = 'stop'; + } + + } + + return $this->output->box($content, 'edit_pages_box'); + } + + /** + * Returns HTML to display the add page links + * + * @param lesson $lesson + * @param int $prevpageid + * @return string + */ + public function add_page_links(lesson $lesson, $prevpageid=false) { + global $CFG; + + $links = array(); + + $importquestionsurl = new moodle_url($CFG->wwwroot.'/mod/lesson/import.php',array('id'=>$this->page->cm->id, 'pageid'=>$prevpageid)); + $links[] = html_link::make($importquestionsurl, get_string('importquestions', 'lesson')); + + $manager = lesson_page_type_manager::get($lesson); + $links = array_merge($links, $manager->get_add_page_type_links($prevpageid)); + + $addquestionurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$this->page->cm->id, 'pageid'=>$prevpageid)); + $links[] = html_link::make($addquestionurl, get_string('addaquestionpagehere', 'lesson')); + + foreach ($links as $key=>$link) { + $links[$key] = $this->output->link($link); + } + + return $this->output->box(implode(" | \n", $links), 'addlinks'); + } + + /** + * Return HTML to display add first page links + * @param lesson $lesson + * @return string + */ + public function add_first_page_links(lesson $lesson) { + global $CFG; + $prevpageid = 0; + + $output = $this->output->heading(get_string("whatdofirst", "lesson"), 3); + $links = array(); + + $importquestionsurl = new moodle_url($CFG->wwwroot.'/mod/lesson/import.php',array('id'=>$this->page->cm->id, 'pageid'=>$prevpageid)); + $links[] = html_link::make($importquestionsurl, get_string('importquestions', 'lesson')); + + $importppturl = new moodle_url($CFG->wwwroot.'/mod/lesson/importppt.php',array('id'=>$this->page->cm->id, 'pageid'=>$prevpageid)); + $links[] = html_link::make($importppturl, get_string('importppt', 'lesson')); + + $manager = lesson_page_type_manager::get($lesson); + $newpagelinks = $manager->get_add_page_type_links($prevpageid); + foreach ($newpagelinks as $link) { + $link->url->param('firstpage', 1); + $links[] = $link; + } + + $addquestionurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$this->page->cm->id, 'pageid'=>$prevpageid, 'firstpage'=>1)); + $links[] = html_link::make($addquestionurl, get_string('addaquestionpage', 'lesson')); + + foreach ($links as $key=>$link) { + $links[$key] = $this->output->link($link); + } + + return $this->output->box($output.'

      '.implode('

      ', $links).'

      ', 'generalbox firstpageoptions'); + } + + /** + * Returns HTML to display action links for a page + * + * @param lesson_page $page + * @param bool $printmove + * @param bool $printaddpage + * @return string + */ + public function page_action_links(lesson_page $page, $printmove, $printaddpage=false) { + global $CFG; + + $actions = array(); + + if ($printmove) { + $printmovehtml = new moodle_url($CFG->wwwroot.'/mod/lesson/lesson.php', array('id'=>$this->page->cm->id, 'action'=>'move', 'pageid'=>$page->id, 'sesskey'=>sesskey())); + $actions[] = html_link::make($printmovehtml, ''.get_string('move').''); + } + $url = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$this->page->cm->id, 'pageid'=>$page->id, 'edit'=>1)); + $actions[] = html_link::make($url, ''.get_string('update').''); + + $url = new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$this->page->cm->id, 'pageid'=>$page->id)); + $actions[] = html_link::make($url, ''.get_string('preview').''); + + $url = new moodle_url($CFG->wwwroot.'/mod/lesson/lesson.php', array('id'=>$this->page->cm->id, 'action'=>'confirmdelete', 'pageid'=>$page->id, 'sesskey'=>sesskey())); + $actions[] = html_link::make($url, ''.get_string('delete').''); + + if ($printaddpage) { + $options = array(); + $manager = lesson_page_type_manager::get($page->lesson); + $links = $manager->get_add_page_type_links($page->id); + foreach ($links as $link) { + $options[$link->url->param('qtype')] = $link->text; + } + $options[0] = get_string('question', 'lesson'); + + $addpageurl = new moodle_url($CFG->wwwroot.'/mod/lesson/editpage.php', array('id'=>$this->page->cm->id, 'pageid'=>$page->id, 'sesskey'=>sesskey())); + $addpageselect = html_select::make_popup_form($addpageurl, 'qtype', $options, 'addpageafter'.$page->id); + $addpageselect->nothinglabel = get_string('addanewpage', 'lesson').'...'; + $addpageselector = $this->output->select($addpageselect); + } + + foreach ($actions as $key=>$action) { + $actions[$key] = $this->output->link($action); + } + if (isset($addpageselector)) { + $actions[] = $addpageselector; + } + + return implode(' ', $actions); + } + + /** + * Prints the on going message to the user. + * + * With custom grading On, displays points + * earned out of total points possible thus far. + * With custom grading Off, displays number of correct + * answers out of total attempted. + * + * @param object $lesson The lesson that the user is taking. + * @return void + **/ + + /** + * Prints the on going message to the user. + * + * With custom grading On, displays points + * earned out of total points possible thus far. + * With custom grading Off, displays number of correct + * answers out of total attempted. + * + * @param lesson $lesson + * @return string + */ + public function ongoing_score(lesson $lesson) { + global $USER, $DB; + + $context = get_context_instance(CONTEXT_MODULE, $this->page->cm->id); + if (has_capability('mod/lesson:manage', $context)) { + return '

      '.get_string('teacherongoingwarning', 'lesson').'

      '; + } else { + $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); + if (isset($USER->modattempts[$lesson->id])) { + $ntries--; + } + $gradeinfo = lesson_grade($lesson, $ntries); + $a = new stdClass; + if ($lesson->custom) { + $a->score = $gradeinfo->earned; + $a->currenthigh = $gradeinfo->total; + return $this->output->box(get_string("ongoingcustom", "lesson", $a), "generalbox boxaligncenter"); + } else { + $a->correct = $gradeinfo->earned; + $a->viewed = $gradeinfo->attempts; + return $this->output->box(get_string("ongoingnormal", "lesson", $a), "generalbox boxaligncenter"); + } + } + } + + /** + * Returns HTML to display a progress bar of progression through a lesson + * + * @param lesson $lesson + * @return string + */ + public function progress_bar(lesson $lesson) { + global $CFG, $USER, $DB; + + $context = get_context_instance(CONTEXT_MODULE, $this->page->cm->id); + + // lesson setting to turn progress bar on or off + if (!$lesson->progressbar) { + return ''; + } + + // catch teachers + if (has_capability('mod/lesson:manage', $context)) { + return $this->output->notification(get_string('progressbarteacherwarning2', 'lesson')); + } + + if (!isset($USER->modattempts[$lesson->id])) { + // all of the lesson pages + $pages = $lesson->load_all_pages(); + foreach ($pages as $page) { + if ($page->prevpageid == 0) { + $pageid = $page->id; // find the first page id + break; + } + } + + // current attempt number + if (!$ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id))) { + $ntries = 0; // may not be necessary + } + + + $viewedpageids = array(); + if ($attempts = $lesson->get_attempts($ntries, true)) { + $viewedpageids = array_merge($viewedpageids, array_keys($attempts)); + } + + // collect all of the branch tables viewed + if ($viewedbranches = $DB->get_records_select("lesson_branch", array ("lessonid"=>$lesson->id, "userid"=>$USER->id, "retry"=>$ntries), 'timeseen DESC', 'pageid, id')) { + $viewedpageids = array_merge($viewedpageids, array_keys($viewedbranches)); + } + + // Filter out the following pages: + // End of Cluster + // End of Branch + // Pages found inside of Clusters + // Do not filter out Cluster Page(s) because we count a cluster as one. + // By keeping the cluster page, we get our 1 + $validpages = array(); + while ($pageid != 0) { + $pageid = $pages[$pageid]->valid_page_and_view($validpages, $viewedpageids); + } + + // progress calculation as a percent + $progress = round(count($viewedpageids)/count($validpages), 2) * 100; + } else { + $progress = 100; + } + + // print out the Progress Bar. Attempted to put as much as possible in the style sheets. + $cells = array(); + if ($progress != 0) { // some browsers do not repsect the 0 width. + $cells[0] = new html_table_cell(); + $cells[0]->style = 'width:'.$progress.'%'; + $cells[0]->set_classes('progress_bar_completed'); + $cells[0]->text = ' '; + } + $cells[] = '
      '; + + $table = new html_table(); + $table->set_classes(array('progress_bar_table', 'center')); + $table->data = array(html_table_row::make($cells)); + + return $this->output->box($this->output->table($table), 'progress_bar'); + } + + /** + * Returns HTML to show the start of a slideshow + * @param lesson $lesson + */ + public function slideshow_start(lesson $lesson) { + $attributes = array(); + $attributes['class'] = 'slideshow'; + $attributes['style'] = 'background-color:'.$lesson->bgcolor.';height:'.$lesson->height.'px;width:'.$lesson->width.'px;'; + $output = $this->output_start_tag('div', $attributes); + } + /** + * Returns HTML to show the end of a slideshow + */ + public function slideshow_end() { + $output = $this->output_end_tag('div'); + } + /** + * Returns a P tag containing contents + * @param string $contents + * @param string $class + */ + public function paragraph($contents, $class='') { + $attributes = array(); + if ($class !== '') { + $attributes['class'] = $class; + } + $output = $this->output_tag('p', $attributes, $contents); + } + /** + * Returns HTML to display add_highscores_form + * @param lesson $lesson + * @return string + */ + public function add_highscores_form(lesson $lesson) { + global $CFG; + $output = $this->output->box_start('generalbox boxaligncenter'); + $output .= $this->output->box_start('mdl-align'); + $output .= '
      + + + '; + $output .= get_string("entername", "lesson").": "; + $output .= $this->output->box("", 'lessonbutton center'); + $output .= "
      "; + $output .= $this->output->box_end(); + $output .= $this->output->box_end(); + return $output; + } +} \ No newline at end of file diff --git a/mod/lesson/report.php b/mod/lesson/report.php index 918445242c..5216adfd64 100644 --- a/mod/lesson/report.php +++ b/mod/lesson/report.php @@ -1,917 +1,547 @@ . + /** * Displays the lesson statistics. * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ - require_once('../../config.php'); - require_once('lib.php'); - require_once('locallib.php'); +require_once('../../config.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); + +$id = required_param('id', PARAM_INT); // Course Module ID +$pageid = optional_param('pageid', NULL, PARAM_INT); // Lesson Page ID +$action = optional_param('action', 'reportoverview', PARAM_ALPHA); // action to take +$nothingtodisplay = false; + +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); - $id = required_param('id', PARAM_INT); // Course Module ID - $pageid = optional_param('pageid', NULL, PARAM_INT); // Lesson Page ID - $action = optional_param('action', 'reportoverview', PARAM_ALPHA); // action to take - $nothingtodisplay = false; +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +require_capability('mod/lesson:manage', $context); - list($cm, $course, $lesson) = lesson_get_basics($id); - $params = array("lessonid" => $lesson->id); - if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) { - $params["groupid"] = $cm->groupingid; - $sql = "SELECT DISTINCT u.* +$params = array("lessonid" => $lesson->id); +if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) { + $params["groupid"] = $cm->groupingid; + $sql = "SELECT DISTINCT u.id, u.* FROM {lesson_attempts} a INNER JOIN {user} u ON u.id = a.userid INNER JOIN {groups_members} gm ON gm.userid = u.id INNER JOIN {groupings_groups} gg ON gm.groupid = :groupid WHERE a.lessonid = :lessonid ORDER BY u.lastname"; - } else { - $sql = "SELECT u.* - FROM {user} u, - {lesson_attempts} a - WHERE a.lessonid = :lessonid and - u.id = a.userid - ORDER BY u.lastname"; - } - - if (! $students = $DB->get_records_sql($sql, $params)) { - $nothingtodisplay = true; - } - -// make sure people are where they should be - require_login($course->id, false, $cm); +} else { + $sql = "SELECT DISTINCT u.id, u.* + FROM {user} u, + {lesson_attempts} a + WHERE a.lessonid = :lessonid and + u.id = a.userid + ORDER BY u.lastname"; +} - $url = new moodle_url($CFG->wwwroot.'/mod/lesson/report.php', array('id'=>$id)); - if ($action !== 'reportoverview') { - $url->param('action', $action); - } - if ($pageid !== NULL) { - $url->param('pageid', $pageid); - } - $PAGE->set_url($url); - $PAGE->navbar->add(get_string('reports', 'lesson'), new moodle_url($CFG->wwwroot.'/mod/lesson/report.php', array('id'=>$id))); +if (! $students = $DB->get_records_sql($sql, $params)) { + $nothingtodisplay = true; +} - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - require_capability('mod/lesson:manage', $context); +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/report.php', array('id'=>$id)); +if ($action !== 'reportoverview') { + $url->param('action', $action); +} +if ($pageid !== NULL) { + $url->param('pageid', $pageid); +} +$PAGE->set_url($url); +$PAGE->navbar->add(get_string('reports', 'lesson'), new moodle_url($CFG->wwwroot.'/mod/lesson/report.php', array('id'=>$id))); +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); /// Process any form data before fetching attempts, grades and times - if (has_capability('mod/lesson:edit', $context) and - $form = data_submitted() and - confirm_sesskey()) { - /// Cycle through array of userids with nested arrays of tries - if (!empty($form->attempts)) { - foreach ($form->attempts as $userid => $tries) { - // Modifier IS VERY IMPORTANT! What does it do? - // Well, it is for when you delete multiple attempts for the same user. - // If you delete try 1 and 3 for a user, then after deleting try 1, try 3 then - // becomes try 2 (because try 1 is gone and all tries after try 1 get decremented). - // So, the modifier makes sure that the submitted try refers to the current try in the - // database - hope this all makes sense :) - $modifier = 0; - - foreach ($tries as $try => $junk) { - $try -= $modifier; - - /// Clean up the timer table - $params = array ("userid" => $userid, "lessonid" => $lesson->id); - $timeid = $DB->get_field_sql("SELECT id FROM {lesson_timer} - WHERE userid = :userid AND lessonid = :lessonid - ORDER BY starttime", $params, $try, 1); - - $DB->delete_records('lesson_timer', array('id' => $timeid)); - - /// Remove the grade from the grades and high_scores tables - $gradeid = $DB->get_field_sql("SELECT id FROM {lesson_grades} - WHERE userid = :userid AND lessonid = :lessonid - ORDER BY completed", $params, $try, 1); - - $DB->delete_records('lesson_grades', array('id' => $gradeid)); - $DB->delete_records('lesson_high_scores', array('gradeid' => $gradeid, 'lessonid' => $lesson->id, 'userid' => $userid)); - - /// Remove attempts and update the retry number - $DB->delete_records('lesson_attempts', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try)); - $DB->execute("UPDATE {lesson_attempts} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try)); - - /// Remove seen branches and update the retry number - $DB->delete_records('lesson_branch', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try)); - $DB->execute("UPDATE {lesson_branch} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try)); - - /// update central gradebook - lesson_update_grades($lesson, $userid); - - $modifier++; - } +if (has_capability('mod/lesson:edit', $context) && $form = data_submitted() && confirm_sesskey()) { +/// Cycle through array of userids with nested arrays of tries + if (!empty($form->attempts)) { + foreach ($form->attempts as $userid => $tries) { + // Modifier IS VERY IMPORTANT! What does it do? + // Well, it is for when you delete multiple attempts for the same user. + // If you delete try 1 and 3 for a user, then after deleting try 1, try 3 then + // becomes try 2 (because try 1 is gone and all tries after try 1 get decremented). + // So, the modifier makes sure that the submitted try refers to the current try in the + // database - hope this all makes sense :) + $modifier = 0; + + foreach ($tries as $try => $junk) { + $try -= $modifier; + + /// Clean up the timer table + $params = array ("userid" => $userid, "lessonid" => $lesson->id); + $timeid = $DB->get_field_sql("SELECT id FROM {lesson_timer} + WHERE userid = :userid AND lessonid = :lessonid + ORDER BY starttime", $params, $try, 1); + + $DB->delete_records('lesson_timer', array('id' => $timeid)); + + /// Remove the grade from the grades and high_scores tables + $gradeid = $DB->get_field_sql("SELECT id FROM {lesson_grades} + WHERE userid = :userid AND lessonid = :lessonid + ORDER BY completed", $params, $try, 1); + + $DB->delete_records('lesson_grades', array('id' => $gradeid)); + $DB->delete_records('lesson_high_scores', array('gradeid' => $gradeid, 'lessonid' => $lesson->id, 'userid' => $userid)); + + /// Remove attempts and update the retry number + $DB->delete_records('lesson_attempts', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try)); + $DB->execute("UPDATE {lesson_attempts} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try)); + + /// Remove seen branches and update the retry number + $DB->delete_records('lesson_branch', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try)); + $DB->execute("UPDATE {lesson_branch} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try)); + + /// update central gradebook + lesson_update_grades($lesson, $userid); + + $modifier++; } - lesson_set_message(get_string('attemptsdeleted', 'lesson'), 'notifysuccess'); } + $lesson->add_message(get_string('attemptsdeleted', 'lesson'), 'notifysuccess'); } +} - if (! $attempts = $DB->get_records('lesson_attempts', array('lessonid' => $lesson->id), 'timeseen')) { - $nothingtodisplay = true; - } +if (! $attempts = $DB->get_records('lesson_attempts', array('lessonid' => $lesson->id), 'timeseen')) { + $nothingtodisplay = true; +} - if (! $grades = $DB->get_records('lesson_grades', array('lessonid' => $lesson->id), 'completed')) { - $grades = array(); - } +if (! $grades = $DB->get_records('lesson_grades', array('lessonid' => $lesson->id), 'completed')) { + $grades = array(); +} - if (! $times = $DB->get_records('lesson_timer', array('lessonid' => $lesson->id), 'starttime')) { - $times = array(); - } +if (! $times = $DB->get_records('lesson_timer', array('lessonid' => $lesson->id), 'starttime')) { + $times = array(); +} - lesson_print_header($cm, $course, $lesson, $action); +echo $lessonoutput->header($lesson, $action); - $course_context = get_context_instance(CONTEXT_COURSE, $course->id); - if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) { - echo ''; - } +$course_context = get_context_instance(CONTEXT_COURSE, $course->id); +if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) { + $seeallgradeslink = new moodle_url($CFG->wwwroot.'/grade/report/grader/index.php', array('id'=>$course->id)); + $seeallgradeslink = html_link::make($seeallgradeslink, get_string('seeallcoursegrades', 'grades')); + echo $OUTPUT->box($OUTPUT->link($seeallgradeslink), 'allcoursegrades'); +} - if ($nothingtodisplay) { - echo $OUTPUT->notification(get_string('nolessonattempts', 'lesson')); - echo $OUTPUT->footer(); - exit(); - } +if ($nothingtodisplay) { + echo $OUTPUT->notification(get_string('nolessonattempts', 'lesson')); + echo $OUTPUT->footer(); + exit(); +} - /************************************************************************** - this action is for default view and overview view - **************************************************************************/ - if ($action == 'reportoverview') { - $studentdata = array(); - - // build an array for output - foreach ($attempts as $attempt) { - // if the user is not in the array or if the retry number is not in the sub array, add the data for that try. - if (!array_key_exists($attempt->userid, $studentdata) || !array_key_exists($attempt->retry, $studentdata[$attempt->userid])) { - // restore/setup defaults - $n = 0; - $timestart = 0; - $timeend = 0; - $usergrade = NULL; - - // search for the grade record for this try. if not there, the nulls defined above will be used. - foreach($grades as $grade) { - // check to see if the grade matches the correct user - if ($grade->userid == $attempt->userid) { - // see if n is = to the retry - if ($n == $attempt->retry) { - // get grade info - $usergrade = round($grade->grade, 2); // round it here so we only have to do it once - break; - } - $n++; // if not equal, then increment n +/************************************************************************** +this action is for default view and overview view +**************************************************************************/ +if ($action == 'reportoverview') { + $studentdata = array(); + + // build an array for output + foreach ($attempts as $attempt) { + // if the user is not in the array or if the retry number is not in the sub array, add the data for that try. + if (!array_key_exists($attempt->userid, $studentdata) || !array_key_exists($attempt->retry, $studentdata[$attempt->userid])) { + // restore/setup defaults + $n = 0; + $timestart = 0; + $timeend = 0; + $usergrade = NULL; + + // search for the grade record for this try. if not there, the nulls defined above will be used. + foreach($grades as $grade) { + // check to see if the grade matches the correct user + if ($grade->userid == $attempt->userid) { + // see if n is = to the retry + if ($n == $attempt->retry) { + // get grade info + $usergrade = round($grade->grade, 2); // round it here so we only have to do it once + break; } + $n++; // if not equal, then increment n } - $n = 0; - // search for the time record for this try. if not there, the nulls defined above will be used. - foreach($times as $time) { - // check to see if the grade matches the correct user - if ($time->userid == $attempt->userid) { - // see if n is = to the retry - if ($n == $attempt->retry) { - // get grade info - $timeend = $time->lessontime; - $timestart = $time->starttime; - break; - } - $n++; // if not equal, then increment n + } + $n = 0; + // search for the time record for this try. if not there, the nulls defined above will be used. + foreach($times as $time) { + // check to see if the grade matches the correct user + if ($time->userid == $attempt->userid) { + // see if n is = to the retry + if ($n == $attempt->retry) { + // get grade info + $timeend = $time->lessontime; + $timestart = $time->starttime; + break; } + $n++; // if not equal, then increment n } - - // build up the array. - // this array represents each student and all of their tries at the lesson - $studentdata[$attempt->userid][$attempt->retry] = array( "timestart" => $timestart, - "timeend" => $timeend, - "grade" => $usergrade, - "try" => $attempt->retry, - "userid" => $attempt->userid); } + + // build up the array. + // this array represents each student and all of their tries at the lesson + $studentdata[$attempt->userid][$attempt->retry] = array( "timestart" => $timestart, + "timeend" => $timeend, + "grade" => $usergrade, + "try" => $attempt->retry, + "userid" => $attempt->userid); } - // set all the stats variables - $numofattempts = 0; - $avescore = 0; - $avetime = 0; - $highscore = NULL; - $lowscore = NULL; - $hightime = NULL; - $lowtime = NULL; - - $table = new html_table(); - - // set up the table object - $table->head = array(get_string('name'), get_string('attempts', 'lesson'), get_string('highscore', 'lesson')); - $table->align = array("center", "left", "left"); - $table->wrap = array("nowrap", "nowrap", "nowrap"); - $table->width = "90%"; - $table->size = array("*", "70%", "*"); - - // print out the $studentdata array - // going through each student that has attempted the lesson, so, each student should have something to be displayed - foreach ($students as $student) { - // check to see if the student has attempts to print out - if (array_key_exists($student->id, $studentdata)) { - // set/reset some variables - $attempts = array(); - // gather the data for each user attempt - $bestgrade = 0; - $bestgradefound = false; - // $tries holds all the tries/retries a student has done - $tries = $studentdata[$student->id]; - $studentname = "{$student->lastname}, $student->firstname"; - foreach ($tries as $try) { - // start to build up the checkbox and link - if (has_capability('mod/lesson:edit', $context)) { - $temp = ' '; - } else { - $temp = ''; - } + } + // set all the stats variables + $numofattempts = 0; + $avescore = 0; + $avetime = 0; + $highscore = NULL; + $lowscore = NULL; + $hightime = NULL; + $lowtime = NULL; + + $table = new html_table(); + + // set up the table object + $table->head = array(get_string('name'), get_string('attempts', 'lesson'), get_string('highscore', 'lesson')); + $table->align = array("center", "left", "left"); + $table->wrap = array("nowrap", "nowrap", "nowrap"); + $table->set_classes(array('standardtable', 'generaltable')); + $table->size = array("*", "70%", "*"); + + // print out the $studentdata array + // going through each student that has attempted the lesson, so, each student should have something to be displayed + foreach ($students as $student) { + // check to see if the student has attempts to print out + if (array_key_exists($student->id, $studentdata)) { + // set/reset some variables + $attempts = array(); + // gather the data for each user attempt + $bestgrade = 0; + $bestgradefound = false; + // $tries holds all the tries/retries a student has done + $tries = $studentdata[$student->id]; + $studentname = "{$student->lastname}, $student->firstname"; + foreach ($tries as $try) { + // start to build up the checkbox and link + if (has_capability('mod/lesson:edit', $context)) { + $temp = ' '; + } else { + $temp = ''; + } - $temp .= "id&action=reportdetail&userid=".$try['userid'].'&try='.$try['try'].'">'; - if ($try["grade"] !== NULL) { // if NULL then not done yet - // this is what the link does when the user has completed the try - $timetotake = $try["timeend"] - $try["timestart"]; - - $temp .= $try["grade"]."%"; - $bestgradefound = true; - if ($try["grade"] > $bestgrade) { - $bestgrade = $try["grade"]; - } - $temp .= " ".userdate($try["timestart"]); - $temp .= ", (".format_time($timetotake).")"; - } else { - // this is what the link does/looks like when the user has not completed the try - $temp .= get_string("notcompleted", "lesson"); - $temp .= " ".userdate($try["timestart"]).""; - $timetotake = NULL; + $temp .= "id&action=reportdetail&userid=".$try['userid'].'&try='.$try['try'].'">'; + if ($try["grade"] !== NULL) { // if NULL then not done yet + // this is what the link does when the user has completed the try + $timetotake = $try["timeend"] - $try["timestart"]; + + $temp .= $try["grade"]."%"; + $bestgradefound = true; + if ($try["grade"] > $bestgrade) { + $bestgrade = $try["grade"]; } - // build up the attempts array - $attempts[] = $temp; - - // run these lines for the stats only if the user finnished the lesson - if ($try["grade"] !== NULL) { - $numofattempts++; - $avescore += $try["grade"]; - $avetime += $timetotake; - if ($try["grade"] > $highscore || $highscore == NULL) { - $highscore = $try["grade"]; - } - if ($try["grade"] < $lowscore || $lowscore == NULL) { - $lowscore = $try["grade"]; - } - if ($timetotake > $hightime || $hightime == NULL) { - $hightime = $timetotake; - } - if ($timetotake < $lowtime || $lowtime == NULL) { - $lowtime = $timetotake; - } + $temp .= " ".userdate($try["timestart"]); + $temp .= ", (".format_time($timetotake).")"; + } else { + // this is what the link does/looks like when the user has not completed the try + $temp .= get_string("notcompleted", "lesson"); + $temp .= " ".userdate($try["timestart"]).""; + $timetotake = NULL; + } + // build up the attempts array + $attempts[] = $temp; + + // run these lines for the stats only if the user finnished the lesson + if ($try["grade"] !== NULL) { + $numofattempts++; + $avescore += $try["grade"]; + $avetime += $timetotake; + if ($try["grade"] > $highscore || $highscore == NULL) { + $highscore = $try["grade"]; + } + if ($try["grade"] < $lowscore || $lowscore == NULL) { + $lowscore = $try["grade"]; + } + if ($timetotake > $hightime || $hightime == NULL) { + $hightime = $timetotake; + } + if ($timetotake < $lowtime || $lowtime == NULL) { + $lowtime = $timetotake; } } - // get line breaks in after each attempt - $attempts = implode("
      \n", $attempts); - // add it to the table data[] object - $table->data[] = array($studentname, $attempts, $bestgrade."%"); } + // get line breaks in after each attempt + $attempts = implode("
      \n", $attempts); + // add it to the table data[] object + $table->data[] = array($studentname, $attempts, $bestgrade."%"); } - // print it all out ! - if (has_capability('mod/lesson:edit', $context)) { - echo "
      \n - \n - id\" />\n - id\" />\n"; - } - echo $OUTPUT->table($table); - - if (has_capability('mod/lesson:edit', $context)) { - echo '
      '. - ''.get_string('selectall').' / '. - ''.get_string('deselectall').' '; - - $select = new html_select(); - $select->options = array('delete' => get_string('deleteselected')); - $select->name = 'attemptaction'; - $select->selectedvalue = 0; - $select->add_action('change', 'submit_form_by_id', array('id' => 'theform')); - echo $OUTPUT->select($select); - - echo '
      '; - } + } + // print it all out ! + if (has_capability('mod/lesson:edit', $context)) { + echo "
      \n + \n + id\" />\n"; + } + echo $OUTPUT->table($table); + if (has_capability('mod/lesson:edit', $context)) { + $checklinks = ''.get_string('selectall').' / '; + $checklinks .=''.get_string('deselectall').''; + $select = new html_select(); + $select->options = array('delete' => get_string('deleteselected')); + $select->name = 'attemptaction'; + $select->selectedvalue = 0; + $select->add_action('change', 'submit_form_by_id', array('id' => 'theform')); + echo $OUTPUT->box($checklinks.$OUTPUT->select($select), 'center'); + echo '
      '; + } - // some stat calculations - if ($numofattempts == 0) { - $avescore = get_string("notcompleted", "lesson"); - } else { - $avescore = format_float($avescore/$numofattempts, 2); - } - if ($avetime == NULL) { - $avetime = get_string("notcompleted", "lesson"); - } else { - $avetime = format_float($avetime/$numofattempts, 0); - $avetime = format_time($avetime); - } - if ($hightime == NULL) { - $hightime = get_string("notcompleted", "lesson"); - } else { - $hightime = format_time($hightime); - } - if ($lowtime == NULL) { - $lowtime = get_string("notcompleted", "lesson"); - } else { - $lowtime = format_time($lowtime); - } - if ($highscore == NULL) { - $highscore = get_string("notcompleted", "lesson"); - } - if ($lowscore == NULL) { - $lowscore = get_string("notcompleted", "lesson"); - } + // some stat calculations + if ($numofattempts == 0) { + $avescore = get_string("notcompleted", "lesson"); + } else { + $avescore = format_float($avescore/$numofattempts, 2); + } + if ($avetime == NULL) { + $avetime = get_string("notcompleted", "lesson"); + } else { + $avetime = format_float($avetime/$numofattempts, 0); + $avetime = format_time($avetime); + } + if ($hightime == NULL) { + $hightime = get_string("notcompleted", "lesson"); + } else { + $hightime = format_time($hightime); + } + if ($lowtime == NULL) { + $lowtime = get_string("notcompleted", "lesson"); + } else { + $lowtime = format_time($lowtime); + } + if ($highscore == NULL) { + $highscore = get_string("notcompleted", "lesson"); + } + if ($lowscore == NULL) { + $lowscore = get_string("notcompleted", "lesson"); + } - // output the stats - echo $OUTPUT->heading(get_string('lessonstats', 'lesson')); - $stattable = new stdClass; - $stattable->head = array(get_string('averagescore', 'lesson'), get_string('averagetime', 'lesson'), - get_string('highscore', 'lesson'), get_string('lowscore', 'lesson'), - get_string('hightime', 'lesson'), get_string('lowtime', 'lesson')); - $stattable->align = array("center", "center", "center", "center", "center", "center"); - $stattable->wrap = array("nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap"); - $stattable->width = "90%"; - $stattable->data[] = array($avescore.'%', $avetime, $highscore.'%', $lowscore.'%', $hightime, $lowtime); - - echo $OUTPUT->table($stattable); -} + // output the stats + echo $OUTPUT->heading(get_string('lessonstats', 'lesson')); + $stattable = new html_table(); + $stattable->head = array(get_string('averagescore', 'lesson'), get_string('averagetime', 'lesson'), + get_string('highscore', 'lesson'), get_string('lowscore', 'lesson'), + get_string('hightime', 'lesson'), get_string('lowtime', 'lesson')); + $stattable->align = array("center", "center", "center", "center", "center", "center"); + $stattable->wrap = array("nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap"); + $stattable->set_classes(array('standardtable', 'generaltable')); + $stattable->data[] = array($avescore.'%', $avetime, $highscore.'%', $lowscore.'%', $hightime, $lowtime); + + echo $OUTPUT->table($stattable); +} else if ($action == 'reportdetail') { /************************************************************************** this action is for a student detailed view and for the general detailed view - General flow of this section of the code - 1. Generate a object which holds values for the statistics for each question/answer - 2. Cycle through all the pages to create a object. Foreach page, see if the student actually answered - the page. Then process the page appropriatly. Display all info about the question, - Highlight correct answers, show how the user answered the question, and display statistics - about each page - 3. Print out info about the try (if needed) - 4. Print out the object which contains all the try info - - **************************************************************************/ - else if ($action == 'reportdetail') { - - $formattextdefoptions = new stdClass; - $formattextdefoptions->para = false; //I'll use it widely in this page - - $userid = optional_param('userid', NULL, PARAM_INT); // if empty, then will display the general detailed view - $try = optional_param('try', NULL, PARAM_INT); - - if (! $lessonpages = $DB->get_records("lesson_pages", array("lessonid" => $lesson->id))) { - print_error('cannotfindpages', 'lesson'); - } - if (! $pageid = $DB->get_field("lesson_pages", "id", array("lessonid" => $lesson->id, "prevpageid" => 0))) { - print_error('cannotfindfirstpage', 'lesson'); + General flow of this section of the code + 1. Generate a object which holds values for the statistics for each question/answer + 2. Cycle through all the pages to create a object. Foreach page, see if the student actually answered + the page. Then process the page appropriatly. Display all info about the question, + Highlight correct answers, show how the user answered the question, and display statistics + about each page + 3. Print out info about the try (if needed) + 4. Print out the object which contains all the try info + +**************************************************************************/ + $formattextdefoptions = new stdClass; + $formattextdefoptions->para = false; //I'll use it widely in this page + + $userid = optional_param('userid', NULL, PARAM_INT); // if empty, then will display the general detailed view + $try = optional_param('try', NULL, PARAM_INT); + + $lessonpages = $lesson->load_all_pages(); + foreach ($lessonpages as $lessonpage) { + if ($lessonpage->prevpageid == 0) { + $pageid = $lessonpage->id; } + } - // now gather the stats into an object - $firstpageid = $pageid; - $pagestats = array(); - while ($pageid != 0) { // EOL - $page = $lessonpages[$pageid]; - $params = array ("lessonid" => $lesson->id, "pageid" => $page->id); - if ($allanswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND pageid = :pageid", $params, "timeseen")) { - // get them ready for processing - $orderedanswers = array(); - foreach ($allanswers as $singleanswer) { - // ordering them like this, will help to find the single attempt record that we want to keep. - $orderedanswers[$singleanswer->userid][$singleanswer->retry][] = $singleanswer; - } - // this is foreach user and for each try for that user, keep one attempt record - foreach ($orderedanswers as $orderedanswer) { - foreach($orderedanswer as $tries) { - if(count($tries) > $lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt - $temp = $tries[$lesson->maxattempts - 1]; - } else { - // else, user attempted the question less than the max, so grab the last one - $temp = end($tries); - } - // page interpretation - // depending on the page type, process stat info for that page - switch ($page->qtype) { - case LESSON_MULTICHOICE: - case LESSON_TRUEFALSE: - if ($page->qoption) { - $userresponse = explode(",", $temp->useranswer); - foreach ($userresponse as $response) { - if (isset($pagestats[$temp->pageid][$response])) { - $pagestats[$temp->pageid][$response]++; - } else { - $pagestats[$temp->pageid][$response] = 1; - } - } - } else { - if (isset($pagestats[$temp->pageid][$temp->answerid])) { - $pagestats[$temp->pageid][$temp->answerid]++; - } else { - $pagestats[$temp->pageid][$temp->answerid] = 1; - } - } - if (isset($pagestats[$temp->pageid]["total"])) { - $pagestats[$temp->pageid]["total"]++; - } else { - $pagestats[$temp->pageid]["total"] = 1; - } - break; - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - if (isset($pagestats[$temp->pageid][$temp->useranswer])) { - $pagestats[$temp->pageid][$temp->useranswer]++; - } else { - $pagestats[$temp->pageid][$temp->useranswer] = 1; - } - if (isset($pagestats[$temp->pageid]["total"])) { - $pagestats[$temp->pageid]["total"]++; - } else { - $pagestats[$temp->pageid]["total"] = 1; - } - break; - case LESSON_MATCHING: - if ($temp->correct) { - if (isset($pagestats[$temp->pageid]["correct"])) { - $pagestats[$temp->pageid]["correct"]++; - } else { - $pagestats[$temp->pageid]["correct"] = 1; - } - } - if (isset($pagestats[$temp->pageid]["total"])) { - $pagestats[$temp->pageid]["total"]++; - } else { - $pagestats[$temp->pageid]["total"] = 1; - } - break; - case LESSON_ESSAY: - $essayinfo = unserialize($temp->useranswer); - if ($essayinfo->graded) { - if (isset($pagestats[$temp->pageid])) { - $essaystats = $pagestats[$temp->pageid]; - $essaystats->totalscore += $essayinfo->score; - $essaystats->total++; - $pagestats[$temp->pageid] = $essaystats; - } else { - $essaystats->totalscore = $essayinfo->score; - $essaystats->total = 1; - $pagestats[$temp->pageid] = $essaystats; - } - } - break; - } - } + // now gather the stats into an object + $firstpageid = $pageid; + $pagestats = array(); + while ($pageid != 0) { // EOL + $page = $lessonpages[$pageid]; + $params = array ("lessonid" => $lesson->id, "pageid" => $page->id); + if ($allanswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND pageid = :pageid", $params, "timeseen")) { + // get them ready for processing + $orderedanswers = array(); + foreach ($allanswers as $singleanswer) { + // ordering them like this, will help to find the single attempt record that we want to keep. + $orderedanswers[$singleanswer->userid][$singleanswer->retry][] = $singleanswer; + } + // this is foreach user and for each try for that user, keep one attempt record + foreach ($orderedanswers as $orderedanswer) { + foreach($orderedanswer as $tries) { + $page->stats($pagestats, $tries); } - - } else { - // no one answered yet... } - //unset($orderedanswers); initialized above now - $pageid = $page->nextpageid; + } else { + // no one answered yet... } + //unset($orderedanswers); initialized above now + $pageid = $page->nextpageid; + } - - - $answerpages = array(); - $answerpage = ""; - $pageid = $firstpageid; - // cycle through all the pages - // foreach page, add to the $answerpages[] array all the data that is needed - // from the question, the users attempt, and the statistics - // grayout pages that the user did not answer and Branch, end of branch, cluster - // and end of cluster pages - while ($pageid != 0) { // EOL - $page = $lessonpages[$pageid]; - $answerpage = new stdClass; - $data =''; - $answerdata = new stdClass; - - $answerpage->title = format_string($page->title); - - $options = new stdClass; - $options->noclean = true; - $answerpage->contents = format_text($page->contents, FORMAT_MOODLE, $options); - - // get the page qtype - switch ($page->qtype) { - case LESSON_ESSAY : - case LESSON_MATCHING : - case LESSON_TRUEFALSE : - case LESSON_NUMERICAL : - $answerpage->qtype = $LESSON_QUESTION_TYPE[$page->qtype]; - $answerpage->grayout = 0; - break; - case LESSON_SHORTANSWER : - $answerpage->qtype = $LESSON_QUESTION_TYPE[$page->qtype]; - if ($page->qoption) { - $answerpage->qtype .= " - ".get_string("casesensitive", "lesson"); - } - $answerpage->grayout = 0; - break; - case LESSON_MULTICHOICE : - $answerpage->qtype = $LESSON_QUESTION_TYPE[$page->qtype]; - if ($page->qoption) { - $answerpage->qtype .= " - ".get_string("multianswer", "lesson"); - } - $answerpage->grayout = 0; - break; - case LESSON_BRANCHTABLE : - $answerpage->qtype = get_string("branchtable", "lesson"); - $answerpage->grayout = 1; - break; - case LESSON_ENDOFBRANCH : - $answerpage->qtype = get_string("endofbranch", "lesson"); - $answerpage->grayout = 1; - break; - case LESSON_CLUSTER : - $answerpage->qtype = get_string("clustertitle", "lesson"); - $answerpage->grayout = 1; - break; - case LESSON_ENDOFCLUSTER : - $answerpage->qtype = get_string("endofclustertitle", "lesson"); - $answerpage->grayout = 1; - break; + $manager = lesson_page_type_manager::get($lesson); + $qtypes = $manager->get_page_type_strings(); + + $answerpages = array(); + $answerpage = ""; + $pageid = $firstpageid; + // cycle through all the pages + // foreach page, add to the $answerpages[] array all the data that is needed + // from the question, the users attempt, and the statistics + // grayout pages that the user did not answer and Branch, end of branch, cluster + // and end of cluster pages + while ($pageid != 0) { // EOL + $page = $lessonpages[$pageid]; + $answerpage = new stdClass; + $data =''; + $answerdata = new stdClass; + + $answerpage->title = format_string($page->title); + + $options = new stdClass; + $options->noclean = true; + $answerpage->contents = format_text($page->contents, FORMAT_MOODLE, $options); + + $answerpage->qtype = $qtypes[$page->qtype].$page->option_description_string(); + $answerpage->grayout = $page->grayout; + + if (empty($userid)) { + // there is no userid, so set these vars and display stats. + $answerpage->grayout = 0; + $useranswer = NULL; + $answerdata->score = NULL; + $answerdata->response = NULL; + } elseif ($useranswers = $DB->get_records("lesson_attempts",array("lessonid"=>$lesson->id, "userid"=>$userid, "retry"=>$try,"pageid"=>$page->id), "timeseen")) { + // get the user's answer for this page + // need to find the right one + $i = 0; + foreach ($useranswers as $userattempt) { + $useranswer = $userattempt; + $i++; + if ($lesson->maxattempts == $i) { + break; // reached maxattempts, break out + } } + } else { + // user did not answer this page, gray it out and set some nulls + $answerpage->grayout = 1; + $useranswer = NULL; + $answerdata->score = NULL; + $answerdata->response = NULL; + } + $i = 0; + $n = 0; + $answerpages[] = $page->report_answers(clone($answerpage), clone($answerdata), $useranswer, $pagestats, $i, $n); + $pageid = $page->nextpageid; + } - if (empty($userid)) { - // there is no userid, so set these vars and display stats. - $answerpage->grayout = 0; - $useranswer = NULL; - $answerdata->score = NULL; - $answerdata->response = NULL; - } elseif ($useranswers = $DB->get_records_select("lesson_attempts", - "lessonid = :lessonid AND userid = :userid AND retry = :retry AND pageid = :pageid", - array("lessonid" => $lesson->id, "userid" => $userid, "retry" => $try, "pageid" => $page->id), "timeseen")) { - // get the user's answer for this page - // need to find the right one - $i = 0; - foreach ($useranswers as $userattempt) { - $useranswer = $userattempt; - $i++; - if ($lesson->maxattempts == $i) { - break; // reached maxattempts, break out - } - } - } else { - // user did not answer this page, gray it out and set some nulls - $answerpage->grayout = 1; - $useranswer = NULL; - $answerdata->score = NULL; - $answerdata->response = NULL; - - } - // build up the answer data - if ($answers = $DB->get_records("lesson_answers", array("pageid" => $page->id), "id")) { - $i = 0; - $n = 0; - // go through each answer and display it properly with statistics, highlight if correct answer, - // and display what the user entered - foreach ($answers as $answer) { - switch ($page->qtype) { - case LESSON_MULTICHOICE: - case LESSON_TRUEFALSE: - if ($page->qoption) { - if ($useranswer == NULL) { - $userresponse = array(); - } else { - $userresponse = explode(",", $useranswer->useranswer); - } - if (in_array($answer->id, $userresponse)) { - // make checked - $data = ""; - if (!isset($answerdata->response)) { - if ($answer->response == NULL) { - if ($useranswer->correct) { - $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); - } else { - $answerdata->response = get_string("thatsthewronganswer", "lesson"); - } - } else { - $answerdata->response = $answer->response; - } - } - if (!isset($answerdata->score)) { - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; - } elseif ($useranswer->correct) { - $answerdata->score = get_string("receivedcredit", "lesson"); - } else { - $answerdata->score = get_string("didnotreceivecredit", "lesson"); - } - } - } else { - // unchecked - $data = ""; - } - if (($answer->score > 0 && $lesson->custom) || (lesson_iscorrect($page->id, $answer->jumpto) && !$lesson->custom)) { - $data .= "".format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions).""; - } else { - $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions); - } - } else { - if ($useranswer != NULL and $answer->id == $useranswer->answerid) { - // make checked - $data = ""; - if ($answer->response == NULL) { - if ($useranswer->correct) { - $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); - } else { - $answerdata->response = get_string("thatsthewronganswer", "lesson"); - } - } else { - $answerdata->response = $answer->response; - } - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; - } elseif ($useranswer->correct) { - $answerdata->score = get_string("receivedcredit", "lesson"); - } else { - $answerdata->score = get_string("didnotreceivecredit", "lesson"); - } - } else { - // unchecked - $data = ""; - } - if (($answer->score > 0 && $lesson->custom) || (lesson_iscorrect($page->id, $answer->jumpto) && !$lesson->custom)) { - $data .= "".format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions).""; - } else { - $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions); - } - } - if (isset($pagestats[$page->id][$answer->id])) { - $percent = $pagestats[$page->id][$answer->id] / $pagestats[$page->id]["total"] * 100; - $percent = round($percent, 2); - $percent .= "% ".get_string("checkedthisone", "lesson"); - } else { - $percent = get_string("noonecheckedthis", "lesson"); - } - - $answerdata->answers[] = array($data, $percent); - break; - case LESSON_SHORTANSWER: - case LESSON_NUMERICAL: - if ($useranswer == NULL && $i == 0) { - // I have the $i == 0 because it is easier to blast through it all at once. - if (isset($pagestats[$page->id])) { - $stats = $pagestats[$page->id]; - $total = $stats["total"]; - unset($stats["total"]); - foreach ($stats as $valentered => $ntimes) { - $data = ''; - $percent = $ntimes / $total * 100; - $percent = round($percent, 2); - $percent .= "% ".get_string("enteredthis", "lesson"); - $answerdata->answers[] = array($data, $percent); - } - } else { - $answerdata->answers[] = array(get_string("nooneansweredthisquestion", "lesson"), " "); - } - $i++; - } else if ($useranswer != NULL and $answer->id == $useranswer->answerid) { - // get in here when a user answer matches one of the answers to the page - $data = ''; - if (isset($pagestats[$page->id][$useranswer->useranswer])) { - $percent = $pagestats[$page->id][$useranswer->useranswer] / $pagestats[$page->id]["total"] * 100; - $percent = round($percent, 2); - $percent .= "% ".get_string("enteredthis", "lesson"); - } else { - $percent = get_string("nooneenteredthis", "lesson"); - } - $answerdata->answers[] = array($data, $percent); - - if ($answer->response == NULL) { - if ($useranswer->correct) { - $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); - } else { - $answerdata->response = get_string("thatsthewronganswer", "lesson"); - } - } else { - $answerdata->response = $answer->response; - } - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; - } elseif ($useranswer->correct) { - $answerdata->score = get_string("receivedcredit", "lesson"); - } else { - $answerdata->score = get_string("didnotreceivecredit", "lesson"); - } - } elseif ($answer == end($answers) && empty($answerdata) && $useranswer != NULL) { - // get in here when what the user entered is not one of the answers - $data = ''; - if (isset($pagestats[$page->id][$useranswer->useranswer])) { - $percent = $pagestats[$page->id][$useranswer->useranswer] / $pagestats[$page->id]["total"] * 100; - $percent = round($percent, 2); - $percent .= "% ".get_string("enteredthis", "lesson"); - } else { - $percent = get_string("nooneenteredthis", "lesson"); - } - $answerdata->answers[] = array($data, $percent); - - $answerdata->response = get_string("thatsthewronganswer", "lesson"); - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": 0"; - } else { - $answerdata->score = get_string("didnotreceivecredit", "lesson"); - } - } - break; - case LESSON_MATCHING: - if ($n == 0 && $useranswer != NULL && $useranswer->correct) { - if ($answer->response == NULL && $useranswer != NULL) { - $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); - } else { - $answerdata->response = $answer->response; - } - } elseif ($n == 1 && $useranswer != NULL && !$useranswer->correct) { - if ($answer->response == NULL && $useranswer != NULL) { - $answerdata->response = get_string("thatsthewronganswer", "lesson"); - } else { - $answerdata->response = $answer->response; - } - } elseif ($n > 1) { - if ($n == 2 && $useranswer != NULL && $useranswer->correct) { - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; - } else { - $answerdata->score = get_string("receivedcredit", "lesson"); - } - } elseif ($n == 3 && $useranswer != NULL && !$useranswer->correct) { - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; - } else { - $answerdata->score = get_string("didnotreceivecredit", "lesson"); - } - } - $data = ""; - if ($useranswer != NULL) { - $userresponse = explode(",", $useranswer->useranswer); - $data .= ""; - } else { - $data .= ""; - } - - if ($n == 2) { - if (isset($pagestats[$page->id])) { - $percent = $pagestats[$page->id]["correct"] / $pagestats[$page->id]["total"] * 100; - $percent = round($percent, 2); - $percent .= "% ".get_string("answeredcorrectly", "lesson"); - } else { - $percent = get_string("nooneansweredthisquestion", "lesson"); - } - } else { - $percent = ""; - } - - $answerdata->answers[] = array($data, $percent); - $i++; - } - $n++; - break; - case LESSON_ESSAY : - if ($useranswer != NULL) { - $essayinfo = unserialize($useranswer->useranswer); - if ($essayinfo->response == NULL) { - $answerdata->response = get_string("nocommentyet", "lesson"); - } else { - $answerdata->response = s($essayinfo->response); - } - if (isset($pagestats[$page->id])) { - $percent = $pagestats[$page->id]->totalscore / $pagestats[$page->id]->total * 100; - $percent = round($percent, 2); - $percent = get_string("averagescore", "lesson").": ". $percent ."%"; - } else { - // dont think this should ever be reached.... - $percent = get_string("nooneansweredthisquestion", "lesson"); - } - if ($essayinfo->graded) { - if ($lesson->custom) { - $answerdata->score = get_string("pointsearned", "lesson").": ".$essayinfo->score; - } elseif ($essayinfo->score) { - $answerdata->score = get_string("receivedcredit", "lesson"); - } else { - $answerdata->score = get_string("didnotreceivecredit", "lesson"); - } - } else { - $answerdata->score = get_string("havenotgradedyet", "lesson"); - } - } else { - $essayinfo->answer = get_string("didnotanswerquestion", "lesson"); - } - - if (isset($pagestats[$page->id])) { - $avescore = $pagestats[$page->id]->totalscore / $pagestats[$page->id]->total; - $avescore = round($avescore, 2); - $avescore = get_string("averagescore", "lesson").": ". $avescore ; - } else { - // dont think this should ever be reached.... - $avescore = get_string("nooneansweredthisquestion", "lesson"); - } - $answerdata->answers[] = array(s($essayinfo->answer), $avescore); - break; - case LESSON_BRANCHTABLE : - $data = "id\" value=\"".strip_tags(format_text($answer->answer, FORMAT_MOODLE,$formattextdefoptions))."\" disabled=\"disabled\"> "; - $data .= get_string('jumpsto', 'lesson', lesson_get_jump_name($answer->jumpto)); - - $answerdata->answers[] = array($data, ""); - $answerpage->grayout = 1; // always grayed out - break; - case LESSON_ENDOFBRANCH : - case LESSON_CLUSTER : - case LESSON_ENDOFCLUSTER : - $data = get_string('jumpsto', 'lesson', lesson_get_jump_name($answer->jumpto)); - - $answerdata->answers[] = array($data, ""); - $answerpage->grayout = 1; // always grayed out - break; - } - if (isset($answerdata)) { - $answerpage->answerdata = $answerdata; - } - } - $answerpages[] = $answerpage; - } - $pageid = $page->nextpageid; + /// actually start printing something + $table = new html_table(); + $table->wrap = array(); + $table->width = "60%"; + if (!empty($userid)) { + // if looking at a students try, print out some basic stats at the top + + // print out users name + //$headingobject->lastname = $students[$userid]->lastname; + //$headingobject->firstname = $students[$userid]->firstname; + //$headingobject->attempt = $try + 1; + //print_heading(get_string("studentattemptlesson", "lesson", $headingobject)); + echo $OUTPUT->heading(get_string('attempt', 'lesson', $try+1)); + + $table->head = array(); + $table->align = array("right", "left"); + $table->set_classes(array('compacttable', 'generaltable')); + + $params = array("lessonid"=>$lesson->id, "userid"=>$userid); + if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed", "*", $try, 1)) { + $grade = -1; + $completed = -1; + } else { + $grade = current($grades); + $completed = $grade->completed; + $grade = round($grade->grade, 2); + } + if (!$times = $DB->get_records_select("lesson_timer", "lessonid = :lessonid and userid = :userid", $params, "starttime", "*", $try, 1)) { + $timetotake = -1; + } else { + $timetotake = current($times); + $timetotake = $timetotake->lessontime - $timetotake->starttime; } - /// actually start printing something - $table = new html_table(); - $table->wrap = array(); - $table->width = "60%"; - - - if (!empty($userid)) { - // if looking at a students try, print out some basic stats at the top - - // print out users name - //$headingobject->lastname = $students[$userid]->lastname; - //$headingobject->firstname = $students[$userid]->firstname; - //$headingobject->attempt = $try + 1; - //print_heading(get_string("studentattemptlesson", "lesson", $headingobject)); - echo $OUTPUT->heading(get_string('attempt', 'lesson', $try+1)); - - $table->head = array(); - $table->align = array("right", "left"); - $table->class = 'generaltable userinfotable'; - - $params = array ("lessonid" => $lesson->id, "userid" => $userid); - if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed", "*", $try, 1)) { - $grade = -1; - $completed = -1; - } else { - $grade = current($grades); - $completed = $grade->completed; - $grade = round($grade->grade, 2); - } - if (!$times = $DB->get_records_select("lesson_timer", "lessonid = :lessonid and userid = :userid", $params, "starttime", "*", $try, 1)) { - $timetotake = -1; - } else { - $timetotake = current($times); - $timetotake = $timetotake->lessontime - $timetotake->starttime; - } + if ($timetotake == -1 || $completed == -1 || $grade == -1) { + $table->align = array("center"); - if ($timetotake == -1 || $completed == -1 || $grade == -1) { - $table->align = array("center"); + $table->data[] = array(get_string("notcompleted", "lesson")); + } else { + $user = $students[$userid]; - $table->data[] = array(get_string("notcompleted", "lesson")); - } else { - $user = $students[$userid]; + $gradeinfo = lesson_grade($lesson, $try, $user->id); - $gradeinfo = lesson_grade($lesson, $try, $user->id); + $table->data[] = array(get_string('name').':', $OUTPUT->user_picture(moodle_user_picture::make($user, $course->id)).fullname($user, true)); + $table->data[] = array(get_string("timetaken", "lesson").":", format_time($timetotake)); + $table->data[] = array(get_string("completed", "lesson").":", userdate($completed)); + $table->data[] = array(get_string('rawgrade', 'lesson').':', $gradeinfo->earned.'/'.$gradeinfo->total); + $table->data[] = array(get_string("grade", "lesson").":", $grade."%"); + } + echo $OUTPUT->table($table); - $table->data[] = array(get_string('name').':', $OUTPUT->user_picture(moodle_user_picture::make($user, $course->id)).fullname($user, true)); - $table->data[] = array(get_string("timetaken", "lesson").":", format_time($timetotake)); - $table->data[] = array(get_string("completed", "lesson").":", userdate($completed)); - $table->data[] = array(get_string('rawgrade', 'lesson').':', $gradeinfo->earned.'/'.$gradeinfo->total); - $table->data[] = array(get_string("grade", "lesson").":", $grade."%"); - } - echo $OUTPUT->table($table); + // Don't want this class for later tables + $table->set_classes(array()); + } - // Don't want this class for later tables - $table->set_classes(); - echo "
      "; - } + $table->align = array("left", "left"); + $table->size = array("70%", "*"); + $table->set_classes(array('compacttable', 'generaltable')); - $table->align = array("left", "left"); - $table->size = array("70%", "*"); - - foreach ($answerpages as $page) { - unset($table->data); - if ($page->grayout) { // set the color of text - $fontstart = ""; - $fontend = ""; - $fontstart2 = $fontstart; - $fontend2 = $fontend; - } else { - $fontstart = ""; - $fontend = ""; - $fontstart2 = ""; - $fontend2 = ""; - } + foreach ($answerpages as $page) { + unset($table->data); + if ($page->grayout) { // set the color of text + $fontstart = ""; + $fontend = ""; + $fontstart2 = $fontstart; + $fontend2 = $fontend; + } else { + $fontstart = ""; + $fontend = ""; + $fontstart2 = ""; + $fontend2 = ""; + } - $table->head = array($fontstart2.$page->qtype.": ".format_string($page->title).$fontend2, $fontstart2.get_string("classstats", "lesson").$fontend2); - $table->data[] = array($fontstart.get_string("question", "lesson").":
      ".$fontend.$fontstart2.$page->contents.$fontend2, " "); - $table->data[] = array($fontstart.get_string("answer", "lesson").":".$fontend); - // apply the font to each answer + $table->head = array($fontstart2.$page->qtype.": ".format_string($page->title).$fontend2, $fontstart2.get_string("classstats", "lesson").$fontend2); + $table->data[] = array($fontstart.get_string("question", "lesson").":
      ".$fontend.$fontstart2.$page->contents.$fontend2, " "); + $table->data[] = array($fontstart.get_string("answer", "lesson").":".$fontend, ' '); + // apply the font to each answer + if (!empty($page->answerdata) && isset($page->answerdata->response)) { foreach ($page->answerdata->answers as $answer){ $modified = array(); foreach ($answer as $single) { @@ -924,16 +554,14 @@ $table->data[] = array($fontstart.get_string("response", "lesson").":
      ".$fontend.$fontstart2.format_text($page->answerdata->response,FORMAT_MOODLE,$formattextdefoptions).$fontend2, " "); } $table->data[] = array($page->answerdata->score, " "); - echo $OUTPUT->table($table); - echo "
      "; + } else { + $table->data[] = array(0, " "); } + echo $OUTPUT->table($table); } - - else { - print_error('unknowaction'); - } +} else { + print_error('unknowaction'); +} /// Finish the page - echo $OUTPUT->footer(); - - +echo $OUTPUT->footer(); diff --git a/mod/lesson/restorelib.php b/mod/lesson/restorelib.php index 505bd58f5a..4ae9cef2aa 100644 --- a/mod/lesson/restorelib.php +++ b/mod/lesson/restorelib.php @@ -1,32 +1,49 @@ . + /** * This php script contains all the stuff to restore lesson mods * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ //This is the "graphical" structure of the lesson mod: // - // lesson_default lesson ----------------------------|--------------------------|--------------------------| - // (UL, pk->id,fk->courseid) (CL,pk->id) | | | - // | | | | - // | lesson_grades lesson_high_scores lesson_timer - // | (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) - // | - // | - // lesson_pages---------------------------| - // (CL,pk->id,fk->lessonid) | - // | | - // | lesson_branch - // | (UL, pk->id,fk->pageid) - // lesson_answers - // (CL,pk->id,fk->pageid) - // | - // | - // | - // lesson_attempts - // (UL,pk->id,fk->answerid) + // lesson ----------------------------|--------------------------|--------------------------| + // (CL,pk->id) | | | + // | | | | + // | lesson_grades lesson_high_scores lesson_timer + // | (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) (UL, pk->id,fk->lessonid) + // | + // | + // lesson_pages---------------------------| + // (CL,pk->id,fk->lessonid) | + // | | + // | lesson_branch + // | (UL, pk->id,fk->pageid) + // lesson_answers + // (CL,pk->id,fk->pageid) + // | + // | + // | + // lesson_attempts + // (UL,pk->id,fk->answerid) // // Meaning: pk->primary key field of the table // fk->foreign key to link with parent @@ -127,12 +144,6 @@ return false; } } - // restore the default for the course. Only do this once by checking for an id for lesson_default - $lessondefault = backup_getid($restore->backup_unique_code,'lesson_default',$restore->course_id); - if (!$lessondefault) { - $status = lesson_default_restore_mods($info,$restore); - } - } } else { $status = false; @@ -611,85 +622,6 @@ return $status; } - //This function restores the lesson_default - function lesson_default_restore_mods($info, $restore) { - global $CFG, $DB; - - $status = true; - - //Get the default array (optional) - if (isset($info['MOD']['#']['DEFAULTS'])) { - $defaults = $info['MOD']['#']['DEFAULTS']; - - //Iterate over defaults (should only be 1!) - for($i = 0; $i < sizeof($defaults); $i++) { - $default_info = $defaults[$i]; - //traverse_xmlize($default_info); //Debug - //print_object ($GLOBALS['traverse_array']); //Debug - //$GLOBALS['traverse_array']=""; //Debug - - //Now, build the lesson_default record structure - $default->course = $restore->course_id; - $default->practice = backup_todb($default_info['#']['PRACTICE']['0']['#']); - $default->modattempts = backup_todb($default_info['#']['MODATTEMPTS']['0']['#']); - $default->usepassword = backup_todb($default_info['#']['USEPASSWORD']['0']['#']); - $default->password = backup_todb($default_info['#']['PASSWORD']['0']['#']); - $default->conditions = backup_todb($default_info['#']['CONDITIONS']['0']['#']); - $default->grade = backup_todb($default_info['#']['GRADE']['0']['#']); - $default->custom = backup_todb($default_info['#']['CUSTOM']['0']['#']); - $default->ongoing = backup_todb($default_info['#']['ONGOING']['0']['#']); - $default->usemaxgrade = backup_todb($default_info['#']['USEMAXGRADE']['0']['#']); - $default->maxanswers = backup_todb($default_info['#']['MAXANSWERS']['0']['#']); - $default->maxattempts = backup_todb($default_info['#']['MAXATTEMPTS']['0']['#']); - $default->review = backup_todb($default_info['#']['REVIEW']['0']['#']); - $default->nextpagedefault = backup_todb($default_info['#']['NEXTPAGEDEFAULT']['0']['#']); - $default->feedback = backup_todb($default_info['#']['FEEDBACK']['0']['#']); - $default->minquestions = backup_todb($default_info['#']['MINQUESTIONS']['0']['#']); - $default->maxpages = backup_todb($default_info['#']['MAXPAGES']['0']['#']); - $default->timed = backup_todb($default_info['#']['TIMED']['0']['#']); - $default->maxtime = backup_todb($default_info['#']['MAXTIME']['0']['#']); - $default->retake = backup_todb($default_info['#']['RETAKE']['0']['#']); - $default->mediaheight = backup_todb($default_info['#']['MEDIAHEIGHT']['0']['#']); - $default->mediawidth = backup_todb($default_info['#']['MEDIAWIDTH']['0']['#']); - $default->mediaclose = backup_todb($default_info['#']['MEDIACLOSE']['0']['#']); - $default->slideshow = backup_todb($default_info['#']['SLIDESHOW']['0']['#']); - $default->width = backup_todb($default_info['#']['WIDTH']['0']['#']); - $default->height = backup_todb($default_info['#']['HEIGHT']['0']['#']); - $default->bgcolor = backup_todb($default_info['#']['BGCOLOR']['0']['#']); - $default->displayleft = backup_todb($default_info['#']['DISPLAYLEFT']['0']['#']); - $default->displayleftif = backup_todb($default_info['#']['DISPLAYLEFTIF']['0']['#']); - $default->progressbar = backup_todb($default_info['#']['PROGRESSBAR']['0']['#']); - $default->highscores = backup_todb($default_info['#']['HIGHSCORES']['0']['#']); - $default->maxhighscores = backup_todb($default_info['#']['MAXHIGHSCORES']['0']['#']); - - //The structure is equal to the db, so insert the lesson_grade - $newid = $DB->insert_record ("lesson_default",$default); - - if ($newid) { - backup_putid($restore->backup_unique_code,'lesson_default', - $restore->course_id, $newid); - } - - //Do some output - if (($i+1) % 50 == 0) { - if (!defined('RESTORE_SILENTLY')) { - echo "."; - if (($i+1) % 1000 == 0) { - echo "
      "; - } - } - backup_flush(300); - } - - if (!$newid) { - $status = false; - } - } - } - - return $status; - } - //Return a content decoded to support interactivities linking. Every module //should have its own. They are called automatically from //lesson_decode_content_links_caller() function in each module diff --git a/mod/lesson/settings.php b/mod/lesson/settings.php new file mode 100644 index 0000000000..04243d1ba7 --- /dev/null +++ b/mod/lesson/settings.php @@ -0,0 +1,65 @@ +. + +/** + * Settings used by the lesson module, were moved from mod_edit + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late + **/ + +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); + +/** Slideshow settings */ +$settings->add(new admin_setting_configtext('lesson_slideshowwidth', get_string('slideshowwidth', 'lesson'), + get_string('configslideshowwidth', 'lesson'), 640, PARAM_INT)); + +$settings->add(new admin_setting_configtext('lesson_slideshowheight', get_string('slideshowheight', 'lesson'), + get_string('configslideshowheight', 'lesson'), 480, PARAM_INT)); + +$settings->add(new admin_setting_configtext('lesson_slideshowbgcolor', get_string('slideshowbgcolor', 'lesson'), + get_string('configslideshowbgcolor', 'lesson'), '#FFFFFF', PARAM_TEXT)); + +/** Media file popup settings */ +$settings->add(new admin_setting_configtext('lesson_mediawidth', get_string('mediawidth', 'lesson'), + get_string('configmediawidth', 'lesson'), 640, PARAM_INT)); + +$settings->add(new admin_setting_configtext('lesson_mediaheight', get_string('mediaheight', 'lesson'), + get_string('configmediaheight', 'lesson'), 480, PARAM_INT)); + +$settings->add(new admin_setting_configcheckbox('lesson_mediaclose', get_string('mediaclose', 'lesson'), + get_string('configmediaclose', 'lesson'), false, PARAM_TEXT)); + +/** Misc lesson settings */ +$settings->add(new admin_setting_configtext('lesson_maxhighscores', get_string('maxhighscores', 'lesson'), + get_string('configmaxhighscores','lesson'), 10, PARAM_INT)); + +/** Default lesson settings */ +$numbers = array(); +for ($i=20; $i>1; $i--) { + $numbers[$i] = $i; +} +$settings->add(new admin_setting_configselect('lesson_maxanswers', get_string('maximumnumberofanswersbranches','lesson'), + get_string('configmaxanswers', 'lesson'), 4, $numbers)); + +$defaultnextpages = array(); +$defaultnextpages[0] = get_string("normal", "lesson"); +$defaultnextpages[LESSON_UNSEENPAGE] = get_string("showanunseenpage", "lesson"); +$defaultnextpages[LESSON_UNANSWEREDPAGE] = get_string("showanunansweredpage", "lesson"); +$settings->add(new admin_setting_configselect('lesson_defaultnextpage', get_string('actionaftercorrectanswer','lesson'), + get_string('configactionaftercorrectanswer', 'lesson'), 0, $defaultnextpages)); diff --git a/mod/lesson/tabs.php b/mod/lesson/tabs.php index 2d715ee70d..b786541147 100644 --- a/mod/lesson/tabs.php +++ b/mod/lesson/tabs.php @@ -1,73 +1,88 @@ . + /** * Sets up the tabs used by the lesson pages for teachers. * * This file was adapted from the mod/quiz/tabs.php * -* @license http://www.gnu.org/copyleft/gpl.html GNU Public License -* @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late */ /// This file to be included so we can assume config.php has already been included. - global $DB; - if (empty($lesson)) { - print_error('cannotcallscript'); - } - if (!isset($currenttab)) { - $currenttab = ''; - } - if (!isset($cm)) { - $cm = get_coursemodule_from_instance('lesson', $lesson->id); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); - } - if (!isset($course)) { - $course = $DB->get_record('course', array('id' => $lesson->course)); - } +global $DB; +if (empty($lesson)) { + print_error('cannotcallscript'); +} +if (!isset($currenttab)) { + $currenttab = ''; +} +if (!isset($cm)) { + $cm = get_coursemodule_from_instance('lesson', $lesson->id); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); +} +if (!isset($course)) { + $course = $DB->get_record('course', array('id' => $lesson->course)); +} - $tabs = $row = $inactive = $activated = array(); +$tabs = $row = $inactive = $activated = array(); /// user attempt count for reports link hover (completed attempts - much faster) - $attemptscount = $DB->count_records('lesson_grades', array('lessonid'=>$lesson->id)); - - $row[] = new tabobject('view', "$CFG->wwwroot/mod/lesson/view.php?id=$cm->id", get_string('preview', 'lesson'), get_string('previewlesson', 'lesson', format_string($lesson->name))); - $row[] = new tabobject('edit', "$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id", get_string('edit', 'lesson'), get_string('edit', 'moodle', format_string($lesson->name))); - $row[] = new tabobject('reports', "$CFG->wwwroot/mod/lesson/report.php?id=$cm->id", get_string('reports', 'lesson'), get_string('viewreports2', 'lesson', $attemptscount)); - if (has_capability('mod/lesson:edit', $context)) { - $row[] = new tabobject('essay', "$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id", get_string('manualgrading', 'lesson')); - } - if ($lesson->highscores) { - $row[] = new tabobject('highscores', "$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id", get_string('highscores', 'lesson')); - } - - $tabs[] = $row; +$attemptscount = $DB->count_records('lesson_grades', array('lessonid'=>$lesson->id)); +$row[] = new tabobject('view', "$CFG->wwwroot/mod/lesson/view.php?id=$cm->id", get_string('preview', 'lesson'), get_string('previewlesson', 'lesson', format_string($lesson->name))); +$row[] = new tabobject('edit', "$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id", get_string('edit', 'lesson'), get_string('edit', 'moodle', format_string($lesson->name))); +$row[] = new tabobject('reports', "$CFG->wwwroot/mod/lesson/report.php?id=$cm->id", get_string('reports', 'lesson'), get_string('viewreports2', 'lesson', $attemptscount)); +if (has_capability('mod/lesson:edit', $context)) { + $row[] = new tabobject('essay', "$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id", get_string('manualgrading', 'lesson')); +} +if ($lesson->highscores) { + $row[] = new tabobject('highscores', "$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id", get_string('highscores', 'lesson')); +} - switch ($currenttab) { - case 'reportoverview': - case 'reportdetail': - /// sub tabs for reports (overview and detail) - $inactive[] = 'reports'; - $activated[] = 'reports'; +$tabs[] = $row; - $row = array(); - $row[] = new tabobject('reportoverview', "$CFG->wwwroot/mod/lesson/report.php?id=$cm->id&action=reportoverview", get_string('overview', 'lesson')); - $row[] = new tabobject('reportdetail', "$CFG->wwwroot/mod/lesson/report.php?id=$cm->id&action=reportdetail", get_string('detailedstats', 'lesson')); - $tabs[] = $row; - break; - case 'collapsed': - case 'full': - case 'single': - /// sub tabs for edit view (collapsed and expanded aka full) - $inactive[] = 'edit'; - $activated[] = 'edit'; - $row = array(); - $row[] = new tabobject('collapsed', "$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id&mode=collapsed", get_string('collapsed', 'lesson')); - $row[] = new tabobject('full', "$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id&mode=full", get_string('full', 'lesson')); - $tabs[] = $row; - break; - } +switch ($currenttab) { + case 'reportoverview': + case 'reportdetail': + /// sub tabs for reports (overview and detail) + $inactive[] = 'reports'; + $activated[] = 'reports'; - print_tabs($tabs, $currenttab, $inactive, $activated); + $row = array(); + $row[] = new tabobject('reportoverview', "$CFG->wwwroot/mod/lesson/report.php?id=$cm->id&action=reportoverview", get_string('overview', 'lesson')); + $row[] = new tabobject('reportdetail', "$CFG->wwwroot/mod/lesson/report.php?id=$cm->id&action=reportdetail", get_string('detailedstats', 'lesson')); + $tabs[] = $row; + break; + case 'collapsed': + case 'full': + case 'single': + /// sub tabs for edit view (collapsed and expanded aka full) + $inactive[] = 'edit'; + $activated[] = 'edit'; + $row = array(); + $row[] = new tabobject('collapsed', "$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id&mode=collapsed", get_string('collapsed', 'lesson')); + $row[] = new tabobject('full', "$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id&mode=full", get_string('full', 'lesson')); + $tabs[] = $row; + break; +} +print_tabs($tabs, $currenttab, $inactive, $activated); diff --git a/mod/lesson/timer.js b/mod/lesson/timer.js index 79089a15fd..aa86931916 100644 --- a/mod/lesson/timer.js +++ b/mod/lesson/timer.js @@ -73,11 +73,9 @@ current = currentDate.getTime(); current = Math.floor(current/1000); + var myclock = ''; if (current > starttime + testlength) { - myclock = ''; - myclock += ''; myclock += "Time is up"; - myclock += ''; stopclock = 1; } else { timeleft = starttime + testlength - current; @@ -92,11 +90,9 @@ if (minutes < 10) { minutes = "0"+minutes; } - myclock = ''; - myclock += ''; myclock += hours+":"+minutes+":"+secs; - myclock += ''; } + myclock += ''; if (old == "true") { document.write(myclock); diff --git a/mod/lesson/version.php b/mod/lesson/version.php index 78d4fb719b..57a8ec790b 100644 --- a/mod/lesson/version.php +++ b/mod/lesson/version.php @@ -1,13 +1,30 @@ . + /** * Code fragment to define the version of lesson * This fragment is called by moodle_needs_upgrading() and /admin/index.php * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ -$module->version = 2008112601; // The current module version (Date: YYYYMMDDXX) +$module->version = 2009120800; // The current module version (Date: YYYYMMDDXX) $module->requires = 2008072401; // Requires this Moodle version $module->cron = 0; // Period for cron to check this module (secs) diff --git a/mod/lesson/view.php b/mod/lesson/view.php index c338b70733..9b0e5f1c95 100644 --- a/mod/lesson/view.php +++ b/mod/lesson/view.php @@ -1,1024 +1,569 @@ . + /** * This page prints a particular instance of lesson * - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package lesson + * @package lesson + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late **/ - require_once(dirname(__FILE__) . '/../../config.php'); - require_once($CFG->dirroot.'/mod/lesson/locallib.php'); - require_once($CFG->dirroot.'/mod/lesson/lib.php'); - require_once($CFG->libdir . '/completionlib.php'); +require_once(dirname(__FILE__) . '/../../config.php'); +require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once($CFG->dirroot.'/mod/lesson/view_form.php'); +require_once($CFG->libdir . '/completionlib.php'); - $id = required_param('id', PARAM_INT); // Course Module ID - $pageid = optional_param('pageid', NULL, PARAM_INT); // Lesson Page ID - $edit = optional_param('edit', -1, PARAM_BOOL); - $userpassword = optional_param('userpassword','',PARAM_CLEAN); +$id = required_param('id', PARAM_INT); // Course Module ID +$pageid = optional_param('pageid', NULL, PARAM_INT); // Lesson Page ID +$edit = optional_param('edit', -1, PARAM_BOOL); +$userpassword = optional_param('userpassword','',PARAM_CLEAN); - list($cm, $course, $lesson) = lesson_get_basics($id); +try { + $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);; + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST)); +} catch (Exception $e) { + print_error('invalidcoursemodule'); +} +require_login($course, false, $cm); - require_login($course->id, false, $cm); +$url = new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$id)); +if ($pageid !== null) { + $url->param('pageid', $pageid); +} +$PAGE->set_url($url); - $context = get_context_instance(CONTEXT_MODULE, $cm->id); +$context = get_context_instance(CONTEXT_MODULE, $cm->id); +$canmanage = has_capability('mod/lesson:manage', $context); + +$lessonoutput = $PAGE->theme->get_renderer('mod_lesson', $PAGE); /// Check these for students only TODO: Find a better method for doing this! /// Check lesson availability /// Check for password /// Check dependencies /// Check for high scores - if (!has_capability('mod/lesson:manage', $context)) { - - if (($lesson->available != 0 and time() < $lesson->available) or - ($lesson->deadline != 0 and time() > $lesson->deadline)) { // Deadline restrictions - if ($lesson->deadline != 0 and time() > $lesson->deadline) { - $message = get_string('lessonclosed', 'lesson', userdate($lesson->deadline)); - } else { - $message = get_string('lessonopen', 'lesson', userdate($lesson->available)); +if (!$canmanage) { + if (!$lesson->is_accessible()) { // Deadline restrictions + echo $lessonoutput->header($lesson); + if ($lesson->deadline != 0 && time() > $lesson->deadline) { + echo $lessonoutput->lesson_inaccessible(get_string('lessonclosed', 'lesson', userdate($lesson->deadline))); + } else { + echo $lessonoutput->lesson_inaccessible(get_string('lessonopen', 'lesson', userdate($lesson->available))); + } + echo $lessonoutput->footer(); + exit(); + } else if ($lesson->usepassword && empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code + $correctpass = false; + if (!empty($userpassword) && (($lesson->password == md5(trim($userpassword))) || ($lesson->password == trim($userpassword)))) { + // with or without md5 for backward compatibility (MDL-11090) + $USER->lessonloggedin[$lesson->id] = true; + if ($lesson->highscores) { + // Logged in - redirect so we go through all of these checks before starting the lesson. + redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id"); } - - lesson_print_header($cm, $course, $lesson); - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo ''; - echo $OUTPUT->box_end(); - echo $OUTPUT->footer(); + } else { + echo $lessonoutput->header($lesson); + echo $lessonoutput->login_prompt($lesson, optional_param('userpassword', 0, PARAM_CLEAN)); + echo $lessonoutput->footer(); exit(); + } + } else if ($lesson->dependency) { // check for dependencies + if ($dependentlesson = $DB->get_record('lesson', array('id' => $lesson->dependency))) { + // lesson exists, so we can proceed + $conditions = unserialize($lesson->conditions); + // assume false for all + $errors = array(); - } else if ($lesson->usepassword and empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code - $correctpass = false; - if (!empty($userpassword)) { - // with or without md5 for backward compatibility (MDL-11090) - if (($lesson->password == md5(trim($userpassword))) or ($lesson->password == trim($userpassword))) { - $USER->lessonloggedin[$lesson->id] = true; - $correctpass = true; - if ($lesson->highscores) { - // Logged in - redirect so we go through all of these checks before starting the lesson. - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id"); + // check for the timespent condition + if ($conditions->timespent) { + $timespent = false; + if ($attempttimes = $DB->get_records('lesson_timer', array("userid"=>$USER->id, "lessonid"=>$dependentlesson->id))) { + // go through all the times and test to see if any of them satisfy the condition + foreach($attempttimes as $attempttime) { + $duration = $attempttime->lessontime - $attempttime->starttime; + if ($conditions->timespent < $duration/60) { + $timespent = true; + } } } - } - - if (!$correctpass) { - lesson_print_header($cm, $course, $lesson); - echo "
      \n"; - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo '
      ' . "\n"; - echo '
      '; - echo '' . "\n"; - if (optional_param('userpassword', 0, PARAM_CLEAN)) { - echo $OUTPUT->notification(get_string('loginfail', 'lesson')); + if (!$timespent) { + $errors[] = get_string('timespenterror', 'lesson', $conditions->timespent); } - - echo get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name))."

      \n". - get_string('enterpassword', 'lesson')."

      \n
      ". - ''. get_string('cancel', 'lesson') .' '; - - lesson_print_submit_link(get_string('continue', 'lesson'), 'password', 'center', 'standardbutton submitbutton'); - echo '
      '; - echo $OUTPUT->box_end(); - echo "
      \n"; - echo $OUTPUT->footer(); - exit(); } - } else if ($lesson->dependency) { // check for dependencies - if ($dependentlesson = $DB->get_record('lesson', array('id' => $lesson->dependency))) { - // lesson exists, so we can proceed - $conditions = unserialize($lesson->conditions); - // assume false for all - $timespent = false; - $completed = false; + // check for the gradebetterthan condition + if($conditions->gradebetterthan) { $gradebetterthan = false; - // check for the timespent condition - if ($conditions->timespent) { - $params = array ("userid" => $USER->id, "lessonid" => $dependentlesson->id); - if ($attempttimes = $DB->get_records_select('lesson_timer', "userid = :userid AND lessonid = :lessonid", $params)) { - // go through all the times and test to see if any of them satisfy the condition - foreach($attempttimes as $attempttime) { - $duration = $attempttime->lessontime - $attempttime->starttime; - if ($conditions->timespent < $duration/60) { - $timespent = true; - } - } - } - } else { - $timespent = true; // there isn't one set - } - - // check for the gradebetterthan condition - if($conditions->gradebetterthan) { - $params = array ("userid" => $USER->id, "lessonid" => $dependentlesson->id); - if ($studentgrades = $DB->get_records_select('lesson_grades', "userid = :userid AND lessonid = :lessonid", $params)) { - // go through all the grades and test to see if any of them satisfy the condition - foreach($studentgrades as $studentgrade) { - if ($studentgrade->grade >= $conditions->gradebetterthan) { - $gradebetterthan = true; - } + if ($studentgrades = $DB->get_records('lesson_grades', array("userid"=>$USER->id, "lessonid"=>$dependentlesson->id))) { + // go through all the grades and test to see if any of them satisfy the condition + foreach($studentgrades as $studentgrade) { + if ($studentgrade->grade >= $conditions->gradebetterthan) { + $gradebetterthan = true; } } - } else { - $gradebetterthan = true; // there isn't one set - } - - // check for the completed condition - if ($conditions->completed) { - if ($DB->count_records('lesson_grades', array('userid'=>$USER->id, 'lessonid'=>$dependentlesson->id))) { - $completed = true; - } - } else { - $completed = true; // not set - } - - $errors = array(); - // collect all of our error statements - if (!$timespent) { - $errors[] = get_string('timespenterror', 'lesson', $conditions->timespent); - } - if (!$completed) { - $errors[] = get_string('completederror', 'lesson'); } if (!$gradebetterthan) { $errors[] = get_string('gradebetterthanerror', 'lesson', $conditions->gradebetterthan); } - if (!empty($errors)) { // print out the errors if any - lesson_print_header($cm, $course, $lesson); - echo '

      '; - echo $OUTPUT->box_start('generalbox boxaligncenter'); - print_string('completethefollowingconditions', 'lesson', $dependentlesson->name); - echo '

      '.implode('
      '.get_string('and', 'lesson').'
      ', $errors).'

      '; - echo $OUTPUT->box_end(); - echo '

      '; - echo $OUTPUT->footer(); - exit(); + } + + // check for the completed condition + if ($conditions->completed) { + if (!$DB->count_records('lesson_grades', array('userid'=>$USER->id, 'lessonid'=>$dependentlesson->id))) { + $errors[] = get_string('completederror', 'lesson'); } } - } else if ($lesson->highscores and !$lesson->practice and !optional_param('viewed', 0, PARAM_INT) and empty($pageid)) { - // Display high scores before starting lesson - redirect("$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id"); + if (!empty($errors)) { // print out the errors if any + echo $lessonoutput->header($lesson); + echo $lessonoutput->dependancy_errors($dependentlesson, $errors); + echo $lessonoutput->footer(); + exit(); + } } + } else if ($lesson->highscores && !$lesson->practice && !optional_param('viewed', 0, PARAM_INT) && empty($pageid)) { + // Display high scores before starting lesson + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/highscores.php', array("id"=>$cm->id))); } - - // set up some general variables - $path = $CFG->wwwroot .'/course'; +} // this is called if a student leaves during a lesson - if($pageid == LESSON_UNSEENBRANCHPAGE) { - $pageid = lesson_unseen_question_jump($lesson->id, $USER->id, $pageid); - } - - // display individual pages and their sets of answers - // if pageid is EOL then the end of the lesson has been reached - // for flow, changed to simple echo for flow styles, michaelp, moved lesson name and page title down - $attemptflag = false; - if (empty($pageid)) { - // make sure there are pages to view - if (!$DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) { - if (!has_capability('mod/lesson:manage', $context)) { - lesson_set_message(get_string('lessonnotready2', 'lesson')); // a nice message to the student +if ($pageid == LESSON_UNSEENBRANCHPAGE) { + $pageid = lesson_unseen_question_jump($lesson, $USER->id, $pageid); +} + +// display individual pages and their sets of answers +// if pageid is EOL then the end of the lesson has been reached +// for flow, changed to simple echo for flow styles, michaelp, moved lesson name and page title down +$attemptflag = false; +if (empty($pageid)) { + // make sure there are pages to view + if (!$DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) { + if (!$canmanage) { + $lesson->add_message(get_string('lessonnotready2', 'lesson')); // a nice message to the student + } else { + if (!$DB->count_records('lesson_pages', array('lessonid'=>$lesson->id))) { + redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); // no pages - redirect to add pages } else { - if (!$DB->count_records('lesson_pages', array('lessonid'=>$lesson->id))) { - redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); // no pages - redirect to add pages - } else { - lesson_set_message(get_string('lessonpagelinkingbroken', 'lesson')); // ok, bad mojo - } + $lesson->add_message(get_string('lessonpagelinkingbroken', 'lesson')); // ok, bad mojo } } + } - add_to_log($course->id, 'lesson', 'start', 'view.php?id='. $cm->id, $lesson->id, $cm->id); - - // if no pageid given see if the lesson has been started - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if ($grades = $DB->get_records_select('lesson_grades', 'lessonid = :lessonid AND userid = :userid', $params, - 'grade DESC')) { - $retries = count($grades); - } else { - $retries = 0; - } - if ($retries) { - $attemptflag = true; - } - - if (isset($USER->modattempts[$lesson->id])) { - unset($USER->modattempts[$lesson->id]); // if no pageid, then student is NOT reviewing - } + add_to_log($course->id, 'lesson', 'start', 'view.php?id='. $cm->id, $lesson->id, $cm->id); - // if there are any questions have been answered correctly in this attempt - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $retries); - if ($attempts = $DB->get_records_select('lesson_attempts', - "lessonid = :lessonid AND userid = :userid AND retry = :retry AND - correct = 1", $params, 'timeseen DESC')) { + // if no pageid given see if the lesson has been started + $retries = $DB->count_records('lesson_grades', array("lessonid" => $lesson->id, "userid" => $USER->id)); + if ($retries > 0) { + $attemptflag = true; + } - foreach ($attempts as $attempt) { - $jumpto = $DB->get_field('lesson_answers', 'jumpto', array('id' => $attempt->answerid)); - // convert the jumpto to a proper page id - if ($jumpto == 0) { // unlikely value! - $lastpageseen = $attempt->pageid; - } elseif ($jumpto == LESSON_NEXTPAGE) { - if (!$lastpageseen = $DB->get_field('lesson_pages', 'nextpageid', array('id' => $attempt->pageid))) { - // no nextpage go to end of lesson - $lastpageseen = LESSON_EOL; - } - } else { - $lastpageseen = $jumpto; - } - break; // only look at the latest correct attempt - } - } else { - $attempts = NULL; - } + if (isset($USER->modattempts[$lesson->id])) { + unset($USER->modattempts[$lesson->id]); // if no pageid, then student is NOT reviewing + } - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $retries); - if ($branchtables = $DB->get_records_select('lesson_branch', - "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, 'timeseen DESC')) { - // in here, user has viewed a branch table - $lastbranchtable = current($branchtables); - if ($attempts != NULL) { - foreach($attempts as $attempt) { - if ($lastbranchtable->timeseen > $attempt->timeseen) { - // branch table was viewed later than the last attempt - $lastpageseen = $lastbranchtable->pageid; - } - break; + // if there are any questions have been answered correctly in this attempt + $corrrectattempts = $lesson->get_attempts($retries, true); + if ($corrrectattempts>0) { + foreach ($corrrectattempts as $attempt) { + $jumpto = $DB->get_field('lesson_answers', 'jumpto', array('id' => $attempt->answerid)); + // convert the jumpto to a proper page id + if ($jumpto == 0) { // unlikely value! + $lastpageseen = $attempt->pageid; + } elseif ($jumpto == LESSON_NEXTPAGE) { + if (!$lastpageseen = $DB->get_field('lesson_pages', 'nextpageid', array('id' => $attempt->pageid))) { + // no nextpage go to end of lesson + $lastpageseen = LESSON_EOL; } } else { - // hasnt answered any questions but has viewed a branch table - $lastpageseen = $lastbranchtable->pageid; + $lastpageseen = $jumpto; } + break; // only look at the latest correct attempt } - //if ($lastpageseen != $firstpageid) { - if (isset($lastpageseen) and $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id, 'retry'=>$retries)) > 0) { - // get the first page - if (!$firstpageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, - 'prevpageid' => 0))) { - print_error('cannotfindfirstpage', 'lesson'); - } - lesson_print_header($cm, $course, $lesson); - if ($lesson->timed) { - if ($lesson->retake) { - echo $OUTPUT->box('

      '. get_string('leftduringtimed', 'lesson') .'

      ', 'generalbox boxaligncenter'); - echo ''; - } else { - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo '
      '; - echo get_string('leftduringtimednoretake', 'lesson'); - echo '

      '; - echo '
      '; - echo $OUTPUT->box_end(); - } - - } else { - echo $OUTPUT->box("

      ".get_string('youhaveseen','lesson').'

      ', - 'generalbox boxaligncenter'); - - echo '
      '; - echo ''. - ''. - get_string('yes').'   '; - echo ''. - ''. - get_string('no').'
      '; - echo '
      '; - } - echo $OUTPUT->footer(); - exit(); - } + } - if ($grades) { - foreach ($grades as $grade) { - $bestgrade = $grade->grade; + if ($branchtables = $DB->get_records('lesson_branch', array("lessonid"=>$lesson->id, "userid"=>$USER->id, "retry"=>$retries), 'timeseen DESC')) { + // in here, user has viewed a branch table + $lastbranchtable = current($branchtables); + if (count($corrrectattempts)>0) { + foreach($corrrectattempts as $attempt) { + if ($lastbranchtable->timeseen > $attempt->timeseen) { + // branch table was viewed later than the last attempt + $lastpageseen = $lastbranchtable->pageid; + } break; } - if (!$lesson->retake) { - lesson_print_header($cm, $course, $lesson, 'view'); - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo "
      "; - echo get_string("noretake", "lesson"); - echo "

      '; - echo "
      "; - echo $OUTPUT->box_end(); - echo $OUTPUT->footer(); - exit(); - //redirect("../../course/view.php?id=$course->id", get_string("alreadytaken", "lesson")); - // allow student to retake course even if they have the maximum grade - // } elseif ($bestgrade == 100) { - // redirect("../../course/view.php?id=$course->id", get_string("maximumgradeachieved", - // "lesson")); - } - } - // start at the first page - if (!$pageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) { - print_error('cannotfindfirstpage', 'lesson'); - } - /// This is the code for starting a timed test - if(!isset($USER->startlesson[$lesson->id]) && !has_capability('mod/lesson:manage', $context)) { - $USER->startlesson[$lesson->id] = true; - $startlesson = new stdClass; - $startlesson->lessonid = $lesson->id; - $startlesson->userid = $USER->id; - $startlesson->starttime = time(); - $startlesson->lessontime = time(); - - $DB->insert_record('lesson_timer', $startlesson); - if ($lesson->timed) { - lesson_set_message(get_string('maxtimewarning', 'lesson', $lesson->maxtime), 'center'); - } + } else { + // hasnt answered any questions but has viewed a branch table + $lastpageseen = $lastbranchtable->pageid; } } - if ($pageid != LESSON_EOL) { - /// This is the code updates the lessontime for a timed test - if ($startlastseen = optional_param('startlastseen', '', PARAM_ALPHA)) { /// this deletes old records not totally sure if this is necessary anymore - if ($startlastseen == 'no') { - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if ($grades = $DB->get_records_select('lesson_grades', "lessonid = :lessonid AND userid = :userid", $params, - 'grade DESC')) { - $retries = count($grades); - } else { - $retries = 0; - } - $DB->delete_records('lesson_attempts', array('userid' => $USER->id, 'lessonid' => $lesson->id, 'retry' => $retries)); - $DB->delete_records('lesson_branch', array('userid' => $USER->id, 'lessonid' => $lesson->id, 'retry' => $retries)); - } - } - - add_to_log($course->id, 'lesson', 'view', 'view.php?id='. $cm->id, $pageid, $cm->id); - - if (!$page = $DB->get_record('lesson_pages', array('id' => $pageid))) { - print_error('cannotfindpages', 'lesson'); - } - - if ($page->qtype == LESSON_CLUSTER) { //this only gets called when a user starts up a new lesson and the first page is a cluster page - if (!has_capability('mod/lesson:manage', $context)) { - // get new id - $pageid = lesson_cluster_jump($lesson->id, $USER->id, $pageid); - // get new page info - if (!$page = $DB->get_record('lesson_pages', array('id' => $pageid))) { - print_error('cannotfindpages', 'lesson'); - } - add_to_log($course->id, 'lesson', 'view', 'view.php?id='. $cm->id, $pageid, $cm->id); - } else { - // get the next page - $pageid = $page->nextpageid; - if (!$page = $DB->get_record('lesson_pages', array('id' => $pageid))) { - print_error('cannotfindpages', 'lesson'); - } - } - } elseif ($page->qtype == LESSON_ENDOFCLUSTER) { // Check for endofclusters - if ($page->nextpageid == 0) { - $nextpageid = LESSON_EOL; - } else { - $nextpageid = $page->nextpageid; - } - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=$nextpageid"); - } else if ($page->qtype == LESSON_ENDOFBRANCH) { // Check for endofbranches - if ($answers = $DB->get_records('lesson_answers', array('pageid' => $page->id), 'id')) { - // print_heading(get_string('endofbranch', 'lesson')); - foreach ($answers as $answer) { - // just need the first answer - if ($answer->jumpto == LESSON_RANDOMBRANCH) { - $answer->jumpto = lesson_unseen_branch_jump($lesson->id, $USER->id); - } elseif ($answer->jumpto == LESSON_CLUSTERJUMP) { - if (!has_capability('mod/lesson:manage', $context)) { - $answer->jumpto = lesson_cluster_jump($lesson->id, $USER->id, $pageid); - } else { - if ($page->nextpageid == 0) { - $answer->jumpto = LESSON_EOL; - } else { - $answer->jumpto = $page->nextpageid; - } - } - } else if ($answer->jumpto == LESSON_NEXTPAGE) { - if ($page->nextpageid == 0) { - $answer->jumpto = LESSON_EOL; - } else { - $answer->jumpto = $page->nextpageid; - } - } else if ($answer->jumpto == 0) { - $answer->jumpto = $page->id; - } else if ($answer->jumpto == LESSON_PREVIOUSPAGE) { - $answer->jumpto = $page->prevpageid; - } - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=$answer->jumpto"); - break; - } + if (isset($lastpageseen) && $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id, 'retry'=>$retries)) > 0) { + echo $lessonoutput->header($lesson); + if ($lesson->timed) { + if ($lesson->retake) { + $continuelink = html_form::make_button($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$cm->id, 'pageid'=>$lesson->firstpageid, 'startlastseen'=>'no'), get_string('continue', 'lesson'), 'get'); + echo $lessonoutput->message(get_string('leftduringtimed', 'lesson'), $continuelink); } else { - print_error('cannotfindanswer', 'lesson'); + $courselink = html_form::make_button($CFG->wwwroot.'/course/view.php', array('id'=>$PAGE->course->id), get_string('returntocourse', 'lesson'), 'get'); + echo $lessonoutput->message(get_string('leftduringtimednoretake', 'lesson'), $courselink); } + } else { + echo $lessonoutput->continue_links($lesson, $lastpageseen); } + echo $lessonoutput->footer(); + exit(); + } - // check to see if the user can see the left menu - if (!has_capability('mod/lesson:manage', $context)) { - $lesson->displayleft = lesson_displayleftif($lesson); + if ($attemptflag) { + if (!$lesson->retake) { + echo $lessonoutput->header($lesson, 'view'); + $courselink = html_form::make_button($CFG->wwwroot.'/course/view.php', array('id'=>$PAGE->course->id), get_string('returntocourse', 'lesson'), 'get'); + echo $lessonoutput->message(get_string("noretake", "lesson"), $courselink); + echo $lessonoutput->footer(); + exit(); } + } + // start at the first page + if (!$pageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) { + print_error('cannotfindfirstpage', 'lesson'); + } + /// This is the code for starting a timed test + if(!isset($USER->startlesson[$lesson->id]) && !$canmanage) { + $lesson->start_timer(); + } +} + +$currenttab = 'view'; +$extraeditbuttons = false; +$lessonpageid = null; +$timer = null; + +if ($pageid != LESSON_EOL) { + /// This is the code updates the lessontime for a timed test + $startlastseen = optional_param('startlastseen', '', PARAM_ALPHA); + if ($startlastseen == 'no') { + // this deletes old records not totally sure if this is necessary anymore + $retries = $DB->count_records('lesson_grades', array('lessonid'=>$lesson->id, 'userid'=>$USER->id)); + $DB->delete_records('lesson_attempts', array('userid' => $USER->id, 'lessonid' => $lesson->id, 'retry' => $retries)); + $DB->delete_records('lesson_branch', array('userid' => $USER->id, 'lessonid' => $lesson->id, 'retry' => $retries)); + } - // This is where several messages (usually warnings) are displayed - // all of this is displayed above the actual page - - // clock code - // get time information for this user - $timer = new stdClass; - if(!has_capability('mod/lesson:manage', $context)) { - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if (!$timer = $DB->get_records_select('lesson_timer', "lessonid = :lessonid AND userid = :userid", $params, 'starttime')) { - print_error('cannotfindtimer', 'lesson'); - } else { - $timer = array_pop($timer); // this will get the latest start time record - } - } + $page = $lesson->load_page($pageid); + // Check if the page is of a special type and if so take any nessecary action + $newpageid = $page->callback_on_view($canmanage); + if (is_numeric($newpageid)) { + $page = $lesson->load_page($newpageid); + } - $startlastseen = optional_param('startlastseen', '', PARAM_ALPHA); - if ($startlastseen == 'yes') { // continue a previous test, need to update the clock (think this option is disabled atm) - $timer->starttime = time() - ($timer->lessontime - $timer->starttime); - $timer->lessontime = time(); - } else if ($startlastseen == 'no') { // starting over - // starting over, so reset the clock - $timer->starttime = time(); - $timer->lessontime = time(); - } + add_to_log($PAGE->course->id, 'lesson', 'view', 'view.php?id='. $PAGE->cm->id, $page->id, $PAGE->cm->id); - // for timed lessons, display clock - if ($lesson->timed) { - if(has_capability('mod/lesson:manage', $context)) { - lesson_set_message(get_string('teachertimerwarning', 'lesson')); - } else { - $timeleft = ($timer->starttime + $lesson->maxtime * 60) - time(); + // This is where several messages (usually warnings) are displayed + // all of this is displayed above the actual page - if ($timeleft <= 0) { - // Out of time - lesson_set_message(get_string('eolstudentoutoftime', 'lesson')); - redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&pageid=".LESSON_EOL."&outoftime=normal"); - die; // Shouldn't be reached, but make sure - } else if ($timeleft < 60) { - // One minute warning - lesson_set_message(get_string('studentoneminwarning', 'lesson')); - } - } - } + // check to see if the user can see the left menu + if (!$canmanage) { + $lesson->displayleft = lesson_displayleftif($lesson); - // update the clock - if (!has_capability('mod/lesson:manage', $context)) { - $timer->lessontime = time(); - $DB->update_record('lesson_timer', $timer); - } + $continue = ($startlastseen !== ''); + $restart = ($continue && $startlastseen == 'yes'); + $timer = $lesson->update_timer($continue, $restart); - /// This is the warning msg for teachers to inform them that cluster and unseen does not work while logged in as a teacher - if(has_capability('mod/lesson:manage', $context)) { - if (lesson_display_teacher_warning($lesson->id)) { - $warningvars->cluster = get_string('clusterjump', 'lesson'); - $warningvars->unseen = get_string('unseenpageinbranch', 'lesson'); - lesson_set_message(get_string('teacherjumpwarning', 'lesson', $warningvars)); + if ($lesson->timed) { + $timeleft = ($timer->starttime + $lesson->maxtime * 60) - time(); + if ($timeleft <= 0) { + // Out of time + $lesson->add_message(get_string('eolstudentoutoftime', 'lesson')); + redirect(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$cm->id,'pageid'=>LESSON_EOL, 'outoftime'=>'normal'))); + die; // Shouldn't be reached, but make sure + } else if ($timeleft < 60) { + // One minute warning + $lesson->add_message(get_string('studentoneminwarning', 'lesson')); } } - if ($page->qtype == LESSON_BRANCHTABLE) { - if ($lesson->minquestions and !has_capability('mod/lesson:manage', $context)) { - // tell student how many questions they have seen, how many are required and their grade - $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - - $gradeinfo = lesson_grade($lesson, $ntries); - - if ($gradeinfo->attempts) { - if ($gradeinfo->nquestions < $lesson->minquestions) { - $a = new stdClass; - $a->nquestions = $gradeinfo->nquestions; - $a->minquestions = $lesson->minquestions; - lesson_set_message(get_string('numberofpagesviewednotice', 'lesson', $a)); - } - lesson_set_message(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'notify'); + if ($page->qtype == LESSON_PAGE_BRANCHTABLE && $lesson->minquestions) { + // tell student how many questions they have seen, how many are required and their grade + $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); + $gradeinfo = lesson_grade($lesson, $ntries); + if ($gradeinfo->attempts) { + if ($gradeinfo->nquestions < $lesson->minquestions) { $a = new stdClass; - $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1); - $a->total = $lesson->grade; - lesson_set_message(get_string('yourcurrentgradeisoutof', 'lesson', $a), 'notify'); + $a->nquestions = $gradeinfo->nquestions; + $a->minquestions = $lesson->minquestions; + $lesson->add_message(get_string('numberofpagesviewednotice', 'lesson', $a)); } + $lesson->add_message(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'notify'); + $a = new stdClass; + $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1); + $a->total = $lesson->grade; + $lesson->add_message(get_string('yourcurrentgradeisoutof', 'lesson', $a), 'notify'); } } - - $PAGE->set_url('mod/lesson/view.php', array('id' => $cm->id, 'pageid' => $page->id)); - $PAGE->set_subpage($page->id); - - if (($edit != -1) and $PAGE->user_allowed_editing()) { - $USER->editing = $edit; - } - - /// Print the page header, heading and tabs - lesson_add_pretend_blocks($PAGE, $cm, $lesson, $timer); - lesson_print_header($cm, $course, $lesson, 'view', 'true', $page->id); - - if ($attemptflag) { - echo $OUTPUT->heading(get_string('attempt', 'lesson', $retries + 1)); - } - - /// This calculates and prints the ongoing score - if ($lesson->ongoing and !empty($pageid)) { - lesson_print_ongoing_score($lesson); - } - - if ($lesson->displayleft) { - echo ''; + } else { + $timer = null; + if ($lesson->timed) { + $lesson->add_message(get_string('teachertimerwarning', 'lesson')); } - - if ($lesson->slideshow && $page->qtype == LESSON_BRANCHTABLE) { // Starts the slideshow div - echo '
      '; + if (lesson_display_teacher_warning($lesson)) { + // This is the warning msg for teachers to inform them that cluster + // and unseen does not work while logged in as a teacher + $warningvars->cluster = get_string('clusterjump', 'lesson'); + $warningvars->unseen = get_string('unseenpageinbranch', 'lesson'); + $lesson->add_message(get_string('teacherjumpwarning', 'lesson', $warningvars)); } + } - // now starting to print the page's contents - if ($page->qtype == LESSON_BRANCHTABLE) { - echo $OUTPUT->heading(format_string($page->title)); - } else { - $lesson->slideshow = false; // turn off slide show for all pages other than LESSON_BRANTCHTABLE - } + $PAGE->set_url('mod/lesson/view.php', array('id' => $cm->id, 'pageid' => $page->id)); + $PAGE->set_subpage($page->id); + $currenttab = 'view'; + $extraeditbuttons = true; + $lessonpageid = $page->id; - if (!$lesson->slideshow) { - $options = new stdClass; - $options->noclean = true; - echo $OUTPUT->box('
      '. - format_text($page->contents, FORMAT_MOODLE, $options). - '
      ', 'generalbox boxaligncenter'); - } + if (($edit != -1) && $PAGE->user_allowed_editing()) { + $USER->editing = $edit; + } + if (is_array($page->answers) && count($page->answers)>0) { // this is for modattempts option. Find the users previous answer to this page, // and then display it below in answer processing if (isset($USER->modattempts[$lesson->id])) { $retries = $DB->count_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - $retries--; - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "pageid" => $page->id, "retry" => $retries); - if (! $attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND pageid = :pageid AND retry = :retry", $params, "timeseen")) { + if (!$attempts = $lesson->get_attempts($retries-1, false, $page->id)) { print_error('cannotfindpreattempt', 'lesson'); } $attempt = end($attempts); + } else { + $attempt = false; } + $lessoncontent = $lessonoutput->display_page($lesson, $page, $attempt); + } else { - // get the answers in a set order, the id order - if ($answers = $DB->get_records("lesson_answers", array("pageid" => $page->id), "id")) { - if ($page->qtype != LESSON_BRANCHTABLE) { // To fix XHTML problem (BT have their own forms) - echo "
      "; - echo '
      '; - echo "id\" />"; - echo ""; - echo ""; - echo ""; - echo $OUTPUT->box_start('generalbox boxaligncenter'); - echo ''; - } - // default format text options - $options = new stdClass; - $options->para = false; // no

      - $options->noclean = true; - // echo "qtype is $page->qtype"; // debug - switch ($page->qtype) { - case LESSON_SHORTANSWER : - case LESSON_NUMERICAL : - if (isset($USER->modattempts[$lesson->id])) { - $value = 'value="'.s($attempt->useranswer).'"'; - } else { - $value = ""; - } - echo '
      '. - ": \n"; - echo '
      '; - echo $OUTPUT->box_end(); - lesson_print_submit_link(get_string('pleaseenteryouranswerinthebox', 'lesson'), 'answerform'); - break; - case LESSON_TRUEFALSE : - shuffle($answers); - $i = 0; - foreach ($answers as $answer) { - echo ''; - if (isset($USER->modattempts[$lesson->id]) && $answer->id == $attempt->answerid) { - $checked = 'checked="checked"'; - } else { - $checked = ''; - } - echo "id}\" $checked />"; - echo ""; - echo "'; - echo ''; - if ($answer != end($answers)) { - echo "
      "; - } - $i++; - } - echo ''; - echo $OUTPUT->box_end(); - lesson_print_submit_link(get_string('pleasecheckoneanswer', 'lesson'), 'answerform'); - break; - case LESSON_MULTICHOICE : - $i = 0; - shuffle($answers); - - foreach ($answers as $answer) { - echo ''; - if ($page->qoption) { - $checked = ''; - if (isset($USER->modattempts[$lesson->id])) { - $answerids = explode(",", $attempt->useranswer); - if (in_array($answer->id, $answerids)) { - $checked = ' checked="checked"'; - } else { - $checked = ''; - } - } - // more than one answer allowed - echo "id}\"$checked />"; - } else { - if (isset($USER->modattempts[$lesson->id]) && $answer->id == $attempt->answerid) { - $checked = ' checked="checked"'; - } else { - $checked = ''; - } - // only one answer allowed - echo "id}\"$checked />"; - } - echo ''; - echo "'; - echo ''; - if ($answer != end($answers)) { - echo '
      '; - } - $i++; - } - echo ''; - echo $OUTPUT->box_end(); - if ($page->qoption) { - $linkname = get_string('pleasecheckoneormoreanswers', 'lesson'); - } else { - $linkname = get_string('pleasecheckoneanswer', 'lesson'); - } - lesson_print_submit_link($linkname, 'answerform'); - break; - - case LESSON_MATCHING : - // don't suffle answers (could be an option??) - foreach ($answers as $answer) { - // get all the response - if ($answer->response != NULL) { - $responses[] = trim($answer->response); - } - } - - $responseoptions = array(); - if (!empty($responses)) { - shuffle($responses); - $responses = array_unique($responses); - foreach ($responses as $response) { - $responseoptions[htmlspecialchars(trim($response))] = $response; - } - } - if (isset($USER->modattempts[$lesson->id])) { - $useranswers = explode(',', $attempt->useranswer); - $t = 0; - } - foreach ($answers as $answer) { - if ($answer->response != NULL) { - echo ''; - echo ": '; - - if (isset($USER->modattempts[$lesson->id])) { - $selected = htmlspecialchars(trim($answers[$useranswers[$t]]->response)); // gets the user's previous answer - echo $OUTPUT->select(html_select::make ($responseoptions, "response[$answer->id]", $selected)); - $t++; - } else { - echo $OUTPUT->select(html_select::make ($responseoptions, "response[$answer->id]")); - } - echo ''; - if ($answer != end($answers)) { - echo '
      '; - } - } - } - echo ''; - echo $OUTPUT->box_end(); - lesson_print_submit_link(get_string('pleasematchtheabovepairs', 'lesson'), 'answerform'); - break; - case LESSON_BRANCHTABLE : - $options = new stdClass; - $options->para = false; - $buttons = array(); - $i = 0; - foreach ($answers as $answer) { - // Each button must have its own form inorder for it to work with JavaScript turned off - $button = "wwwroot/mod/lesson/lesson.php\">\n". - '
      '. - "id\" />\n". - "\n". - "\n". - "\n". - "jumpto\" />\n". - lesson_print_submit_link(strip_tags(format_text($answer->answer, FORMAT_MOODLE, $options)), "answerform$i", '', '', '', '', true). - '
      '. - ''; - - $buttons[] = $button; - $i++; - } + $nextpage = $lesson->get_next_page($page->nextpageid); - /// Set the orientation - if ($page->layout) { - $orientation = 'horizontal'; - } else { - $orientation = 'vertical'; - } + $data = new stdClass; + $data->id = $PAGE->cm->id; + $data->newpageid = $nextpage->id; - $fullbuttonhtml = "\n
      \n" . - implode("\n", $buttons). - "\n
      \n"; - - if ($lesson->slideshow) { - $options = new stdClass; - $options->noclean = true; - echo '
      '.format_text($page->contents, FORMAT_MOODLE, $options)."
      \n"; - echo '
      '; - echo $fullbuttonhtml; - } else { - echo $fullbuttonhtml; - } + $mform = lesson_page_without_answers(); + $mform->set_data($data); + ob_start(); + $mform->display(); + $lessoncontent = ob_get_contents(); + ob_end_clean(); + } - break; - case LESSON_ESSAY : - if (isset($USER->modattempts[$lesson->id])) { - $essayinfo = unserialize($attempt->useranswer); - $value = s($essayinfo->answer); - } else { - $value = ""; + lesson_add_pretend_blocks($PAGE, $cm, $lesson, $timer); + echo $lessonoutput->header($lesson, $currenttab, $extraeditbuttons, $lessonpageid); + if ($attemptflag) { + echo $OUTPUT->heading(get_string('attempt', 'lesson', $retries)); + } + /// This calculates and prints the ongoing score + if ($lesson->ongoing && !empty($pageid)) { + echo $lessonoutput->ongoing_score($lesson); + } + if ($lesson->displayleft) { + echo ''; + } + echo $lessoncontent; + echo $lessonoutput->slideshow_end(); + echo $lessonoutput->progress_bar($lesson); + echo $lessonoutput->footer(); + +} else { + + $lessoncontent = ''; + // end of lesson reached work out grade + // Used to check to see if the student ran out of time + $outoftime = optional_param('outoftime', '', PARAM_ALPHA); + + // Update the clock / get time information for this user + add_to_log($course->id, "lesson", "end", "view.php?id=".$PAGE->cm->id, "$lesson->id", $PAGE->cm->id); + + $lessoncontent .= $OUTPUT->heading(get_string("congratulations", "lesson")); + $lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter'); + $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); + if (isset($USER->modattempts[$lesson->id])) { + $ntries--; // need to look at the old attempts :) + } + if (!$canmanage) { + $lesson->stop_timer(); + $gradeinfo = lesson_grade($lesson, $ntries); + + if ($gradeinfo->attempts) { + if (!$lesson->custom) { + $lessoncontent .= $lessonoutput->paragraph(get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions), 'center'); + if ($lesson->minquestions) { + if ($gradeinfo->nquestions < $lesson->minquestions) { + // print a warning and set nviewed to minquestions + $lessoncontent .= $lessonoutput->paragraph(get_string("youshouldview", "lesson", $lesson->minquestions), 'center'); } - echo ':'. - '\n"; - echo ''; - echo $OUTPUT->box_end(); - lesson_print_submit_link(get_string('pleaseenteryouranswerinthebox', 'lesson'), 'answerform'); - break; - default: // close the tags MDL-7861 - echo (''); - echo $OUTPUT->box_end(); - break; + } + $lessoncontent .= $lessonoutput->paragraph(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'center'); } - if ($page->qtype != LESSON_BRANCHTABLE) { // To fix XHTML problem (BT have their own forms) - echo ''; - echo "\n"; + $a = new stdClass; + $a->score = $gradeinfo->earned; + $a->grade = $gradeinfo->total; + if ($gradeinfo->nmanual) { + $a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints; + $a->essayquestions = $gradeinfo->nmanual; + $lessoncontent .= $OUTPUT->box(get_string("displayscorewithessays", "lesson", $a), 'center'); + } else { + $lessoncontent .= $OUTPUT->box(get_string("displayscorewithoutessays", "lesson", $a), 'center'); } - } else { - // a page without answers - find the next (logical) page - echo "
      wwwroot/mod/lesson/view.php\">\n"; - echo '
      '; - echo "id\" />\n"; - if ($lesson->nextpagedefault) { - // in Flash Card mode... - // ...first get number of retakes - $nretakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - // ...then get the page ids (lessonid the 5th param is needed to make $DB->get_records play) - $allpages = $DB->get_records("lesson_pages", array("lessonid" => $lesson->id), "id", "id,lessonid"); - shuffle ($allpages); - $found = false; - if ($lesson->nextpagedefault == LESSON_UNSEENPAGE) { - foreach ($allpages as $thispage) { - if (!$DB->count_records("lesson_attempts", array("pageid"=>$thispage->id, "userid"=>$USER->id, "retry"=>$nretakes))) { - $found = true; - break; - } - } - } elseif ($lesson->nextpagedefault == LESSON_UNANSWEREDPAGE) { - foreach ($allpages as $thispage) { - if (!$DB->count_records("lesson_attempts", array('pageid'=>$thispage->id, - 'userid'=>$USER->id, 'correct'=>1, 'retry'=>$nretakes))) { - $found = true; - break; - } - } - } - if ($found) { - $newpageid = $thispage->id; - if ($lesson->maxpages) { - // check number of pages viewed (in the lesson) - if ($DB->count_records("lesson_attempts", array("lessonid"=>$lesson->id, "userid"=>$USER->id, - "retry"=>$nretakes)) >= $lesson->maxpages) { - $newpageid = LESSON_EOL; - } + $a = new stdClass; + $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1); + $a->total = $lesson->grade; + $lessoncontent .= $lessonoutput->paragraph(get_string("yourcurrentgradeisoutof", "lesson", $a), 'center'); + + $grade->lessonid = $lesson->id; + $grade->userid = $USER->id; + $grade->grade = $gradeinfo->grade; + $grade->completed = time(); + if (!$lesson->practice) { + if (isset($USER->modattempts[$lesson->id])) { // if reviewing, make sure update old grade record + if (!$grades = $DB->get_records("lesson_grades", array("lessonid" => $lesson->id, "userid" => $USER->id), "completed DESC", '*', 0, 1)) { + print_error('cannotfindgrade', 'lesson'); } + $oldgrade = array_shift($grades); + $grade->id = $oldgrade->id; + $DB->update_record("lesson_grades", $grade); } else { - $newpageid = LESSON_EOL; + $newgradeid = $DB->insert_record("lesson_grades", $grade); } } else { - // in normal lesson mode... - if (!$newpageid = $DB->get_field("lesson_pages", "nextpageid", array("id" => $pageid))) { - // this is the last page - flag end of lesson - $newpageid = LESSON_EOL; - } + $DB->delete_records("lesson_attempts", array("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries)); } - echo "\n"; - lesson_print_submit_link(get_string('continue', 'lesson'), 'pageform'); - echo '
      '; - echo "
      \n"; - } - - // Finish of the page - lesson_print_progress_bar($lesson, $course); - - } else { - // end of lesson reached work out grade - - // Used to check to see if the student ran out of time - $outoftime = optional_param('outoftime', '', PARAM_ALPHA); - - // Update the clock / get time information for this user - if (!has_capability('mod/lesson:manage', $context)) { - unset($USER->startlesson[$lesson->id]); - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if (!$timer = $DB->get_records_select('lesson_timer', "lessonid = :lessonid AND userid = :userid", $params, 'starttime')) { - print_error('cannotfindtimer', 'lesson'); + } else { + if ($lesson->timed) { + if ($outoftime == 'normal') { + $grade = new stdClass; + $grade->lessonid = $lesson->id; + $grade->userid = $USER->id; + $grade->grade = 0; + $grade->completed = time(); + if (!$lesson->practice) { + $newgradeid = $DB->insert_record("lesson_grades", $grade); + } + $lessoncontent .= get_string("eolstudentoutoftimenoanswers", "lesson"); + } } else { - $timer = array_pop($timer); // this will get the latest start time record + $lessoncontent .= get_string("welldone", "lesson"); } - $timer->lessontime = time(); - - $DB->update_record("lesson_timer", $timer); } - add_to_log($course->id, "lesson", "end", "view.php?id=$cm->id", "$lesson->id", $cm->id); + // update central gradebook + lesson_update_grades($lesson, $USER->id); - lesson_add_pretend_blocks($PAGE, $cm, $lesson, $timer); - lesson_print_header($cm, $course, $lesson, 'view'); - echo $OUTPUT->heading(get_string("congratulations", "lesson")); - echo $OUTPUT->box_start('generalbox boxaligncenter'); - $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id)); - if (isset($USER->modattempts[$lesson->id])) { - $ntries--; // need to look at the old attempts :) - } - if (!has_capability('mod/lesson:manage', $context)) { + } else { + // display for teacher + $lessoncontent .= $lessonoutput->paragraph(get_string("displayofgrade", "lesson"), 'center'); + } + $lessoncontent .= $OUTPUT->box_end(); //End of Lesson button to Continue. - $gradeinfo = lesson_grade($lesson, $ntries); + // after all the grade processing, check to see if "Show Grades" is off for the course + // if yes, redirect to the course page + if (!$course->showgrades) { + redirect(new moodle_url($CFG->wwwroot.'/course/view.php', array('id'=>$course->id))); + } - if ($gradeinfo->attempts) { - if (!$lesson->custom) { - echo "

      ".get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions). - "

      \n"; - if ($lesson->minquestions) { - if ($gradeinfo->nquestions < $lesson->minquestions) { - // print a warning and set nviewed to minquestions - echo "

      ".get_string("youshouldview", "lesson", - $lesson->minquestions)."

      \n"; - } - } - echo "

      ".get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned). - "

      \n"; - } - $a = new stdClass; - $a->score = $gradeinfo->earned; - $a->grade = $gradeinfo->total; - if ($gradeinfo->nmanual) { - $a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints; - $a->essayquestions = $gradeinfo->nmanual; - echo "
      ".get_string("displayscorewithessays", "lesson", $a)."
      "; - } else { - echo "
      ".get_string("displayscorewithoutessays", "lesson", $a)."
      "; + // high scores code + if ($lesson->highscores && !$canmanage && !$lesson->practice) { + $lessoncontent .= $OUTPUT->box_start('center'); + if ($grades = $DB->get_records("lesson_grades", array("lessonid" => $lesson->id), "completed")) { + $madeit = false; + if ($highscores = $DB->get_records("lesson_high_scores", array("lessonid" => $lesson->id))) { + // get all the high scores into an array + $topscores = array(); + $uniquescores = array(); + foreach ($highscores as $highscore) { + $grade = $grades[$highscore->gradeid]->grade; + $topscores[] = $grade; + $uniquescores[$grade] = 1; } - $a = new stdClass; - $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1); - $a->total = $lesson->grade; - echo "

      ".get_string('yourcurrentgradeisoutof', 'lesson', $a)."

      \n"; + // sort to find the lowest score + sort($topscores); + $lowscore = $topscores[0]; - $grade->lessonid = $lesson->id; - $grade->userid = $USER->id; - $grade->grade = $gradeinfo->grade; - $grade->completed = time(); - if (!$lesson->practice) { - if (isset($USER->modattempts[$lesson->id])) { // if reviewing, make sure update old grade record - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id); - if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed")) { - print_error('cannotfindgrade', 'lesson'); - } - $oldgrade = end($grades); - $grade->id = $oldgrade->id; - $DB->update_record("lesson_grades", $grade); - } else { - $newgradeid = $DB->insert_record("lesson_grades", $grade); - } - } else { - $DB->delete_records("lesson_attempts", array("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries)); + if ($gradeinfo->grade >= $lowscore || count($uniquescores) <= $lesson->maxhighscores) { + $madeit = true; } + } + if (!$highscores or $madeit) { + $lessoncontent .= $lessonoutput->paragraph(get_string("youmadehighscore", "lesson", $lesson->maxhighscores), 'center'); + $params = array('id'=>$PAGE->cm->id, 'sesskey'=>sesskey()); + $highscoresbutton = html_form::make_button($CFG->wwwroot.'/mod/lesson/highscores.php', $params, get_string('clicktopost', 'lesson')); + $lessoncontent .= $OUTPUT->button($highscoresbutton); } else { - if ($lesson->timed) { - if ($outoftime == 'normal') { - $grade = new stdClass; - $grade->lessonid = $lesson->id; - $grade->userid = $USER->id; - $grade->grade = 0; - $grade->completed = time(); - if (!$lesson->practice) { - $newgradeid = $DB->insert_record("lesson_grades", $grade); - } - echo get_string("eolstudentoutoftimenoanswers", "lesson"); - } - } else { - echo get_string("welldone", "lesson"); - } + $lessoncontent .= get_string("nothighscore", "lesson", $lesson->maxhighscores)."
      "; } - - // update central gradebook - lesson_update_grades($lesson, $USER->id); - - } else { - // display for teacher - echo "

      ".get_string("displayofgrade", "lesson")."

      \n"; } - echo $OUTPUT->box_end(); //End of Lesson button to Continue. - - // after all the grade processing, check to see if "Show Grades" is off for the course - // if yes, redirect to the course page - if (!$course->showgrades) { - redirect($CFG->wwwroot.'/course/view.php?id='.$course->id); - } - - // high scores code - if ($lesson->highscores && !has_capability('mod/lesson:manage', $context) && !$lesson->practice) { - echo "

      "; - $params = array ("lessonid" => $lesson->id); - if ($grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid", $params, "completed")) { - $madeit = false; - if ($highscores = $DB->get_records_select("lesson_high_scores", "lessonid = :lessonid", $params)) { - // get all the high scores into an array - $topscores = array(); - $uniquescores = array(); - foreach ($highscores as $highscore) { - $grade = $grades[$highscore->gradeid]->grade; - $topscores[] = $grade; - $uniquescores[$grade] = 1; - } - // sort to find the lowest score - sort($topscores); - $lowscore = $topscores[0]; + $link = html_link::make(new moodle_url($CFG->wwwroot.'/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id, 'link'=>'1')), get_string('viewhighscores', 'lesson')); + $link->set_classes(array('centerpadded','lessonbutton','standardbutton')); + $lessoncontent .= $OUTPUT->link($link); + $lessoncontent .= $OUTPUT->box_end(); + } - if ($gradeinfo->grade >= $lowscore || count($uniquescores) <= $lesson->maxhighscores) { - $madeit = true; - } - } - if (!$highscores or $madeit) { - echo '

      '.get_string("youmadehighscore", "lesson", $lesson->maxhighscores). - '

      -
      -
      - - - -

      '; - lesson_print_submit_link(get_string('clicktopost', 'lesson'), 'highscores'); - echo '

      -
      -
      '; - } else { - echo get_string("nothighscore", "lesson", $lesson->maxhighscores)."
      "; - } - } - echo "
      '; - echo "
      "; - } + if ($lesson->modattempts && !$canmanage) { + // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time + // look at the attempt records to find the first QUESTION page that the user answered, then use that page id + // to pass to view again. This is slick cause it wont call the empty($pageid) code + // $ntries is decremented above + if (!$attempts = $lesson->get_attempts($ntries)) { + $attempts = array(); + } + $firstattempt = current($attempts); + $pageid = $firstattempt->pageid; + // IF the student wishes to review, need to know the last question page that the student answered. This will help to make + // sure that the student can leave the lesson via pushing the continue button. + $lastattempt = end($attempts); + $USER->modattempts[$lesson->id] = $lastattempt->pageid; + + $link = html_link::make(new moodle_url($CFG->wwwroot.'/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$pageid)), get_string('reviewlesson', 'lesson')); + $link->set_classes(array('centerpadded','lessonbutton','standardbutton')); + $lessoncontent .= $OUTPUT->link($link); + + } elseif ($lesson->modattempts && $canmanage) { + $lessoncontent .= $lessonoutput->paragraph(get_string("modattemptsnoteacher", "lesson"), 'centerpadded'); + } - if ($lesson->modattempts && !has_capability('mod/lesson:manage', $context)) { - // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time - // look at the attempt records to find the first QUESTION page that the user answered, then use that page id - // to pass to view again. This is slick cause it wont call the empty($pageid) code - // $ntries is decremented above - $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries); - if (!$attempts = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen")) { - $attempts = array(); - } - $firstattempt = current($attempts); - $pageid = $firstattempt->pageid; - // IF the student wishes to review, need to know the last question page that the student answered. This will help to make - // sure that the student can leave the lesson via pushing the continue button. - $lastattempt = end($attempts); - $USER->modattempts[$lesson->id] = $lastattempt->pageid; - echo "\n"; - } elseif ($lesson->modattempts && has_capability('mod/lesson:manage', $context)) { - echo "

      ".get_string("modattemptsnoteacher", "lesson")."

      "; + if ($lesson->activitylink) { + $link = $lesson->link_for_activitylink(); + if ($link instanceof html_link) { + $lessoncontent .= $OUTPUT->link($link); } + } - if ($lesson->activitylink) { - if ($module = $DB->get_record('course_modules', array('id' => $lesson->activitylink))) { - if ($modname = $DB->get_field('modules', 'name', array('id' => $module->module))) - if ($instance = $DB->get_record($modname, array('id' => $module->instance))) { - echo "\n"; - } - } - } + $link = html_link::make(new moodle_url($CFG->wwwroot.'/course/view.php', array('id'=>$course->id)), get_string('returnto', 'lesson', format_string($course->fullname, true))); + $link->set_classes(array('centerpadded','lessonbutton','standardbutton')); + $lessoncontent .= $OUTPUT->link($link); - echo "\n"; - echo "\n"; - } + $link = html_link::make(new moodle_url($CFG->wwwroot.'/grade/index.php', array('id'=>$course->id)), get_string('viewgrades', 'lesson')); + $link->set_classes(array('centerpadded','lessonbutton','standardbutton')); + $lessoncontent .= $OUTPUT->link($link); -/// Finish the page - echo $OUTPUT->footer(); + lesson_add_pretend_blocks($PAGE, $cm, $lesson, $timer); + echo $lessonoutput->header($lesson, $currenttab, $extraeditbuttons, $lessonpageid); + echo $lessoncontent; + echo $lessonoutput->footer(); +} /// Mark as viewed - $completion=new completion_info($course); - $completion->set_module_viewed($cm); - +$completion=new completion_info($course); +$completion->set_module_viewed($cm); diff --git a/mod/lesson/view_form.php b/mod/lesson/view_form.php new file mode 100644 index 0000000000..510a282530 --- /dev/null +++ b/mod/lesson/view_form.php @@ -0,0 +1,53 @@ +. + +/** + * Lesson page without answers + * + * @package lesson + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ + +/** + * Include formslib if it has not already been included + */ +require_once($CFG->libdir.'/formslib.php'); + +/** + * Lesson page without answers + * + * @copyright 2009 Sam Hemelryk + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + **/ +class lesson_page_without_answers extends moodleform { + + public function definition() { + + $mform = $this->_form; + + $mform->addElement('hidden', 'id'); + $mform->setType('id', PARAM_INT); + + $mform->addElement('hidden', 'pageid'); + $mform->setType('pageid', PARAM_INT); + + $this->add_action_buttons(null, get_string("continue", "lesson")); + + } + +} \ No newline at end of file -- 2.39.5