From 707d50d1c8c15db406b3135c09972f4fec12dbf3 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Wed, 25 Jan 2017 12:59:44 +0100 Subject: [PATCH] MDL-57760 mod_lesson: New WS mod_lesson_get_pages_possible_jumps --- mod/lesson/classes/external.php | 95 ++++++++++++++++++ mod/lesson/db/services.php | 8 ++ mod/lesson/locallib.php | 148 ++++++++++++++++------------- mod/lesson/tests/external_test.php | 46 +++++++++ mod/lesson/version.php | 2 +- 5 files changed, 232 insertions(+), 67 deletions(-) diff --git a/mod/lesson/classes/external.php b/mod/lesson/classes/external.php index 6945716afeb..7b224c3f03d 100644 --- a/mod/lesson/classes/external.php +++ b/mod/lesson/classes/external.php @@ -1883,4 +1883,99 @@ class mod_lesson_external extends external_api { ) ); } + + /** + * Describes the parameters for get_pages_possible_jumps. + * + * @return external_external_function_parameters + * @since Moodle 3.3 + */ + public static function get_pages_possible_jumps_parameters() { + return new external_function_parameters ( + array( + 'lessonid' => new external_value(PARAM_INT, 'lesson instance id'), + ) + ); + } + + /** + * Return all the possible jumps for the pages in a given lesson. + * + * You may expect different results on consecutive executions due to the random nature of the lesson module. + * + * @param int $lessonid lesson instance id + * @return array of warnings and possible jumps + * @since Moodle 3.3 + * @throws moodle_exception + */ + public static function get_pages_possible_jumps($lessonid) { + global $USER; + + $params = array('lessonid' => $lessonid); + $params = self::validate_parameters(self::get_pages_possible_jumps_parameters(), $params); + + $warnings = $jumps = array(); + + list($lesson, $course, $cm, $context) = self::validate_lesson($params['lessonid']); + + // Only return for managers or if offline attempts are enabled. + if ($lesson->can_manage() || $lesson->allowofflineattempts) { + + $lessonpages = $lesson->load_all_pages(); + foreach ($lessonpages as $page) { + $jump = array(); + $jump['pageid'] = $page->id; + + $answers = $page->get_answers(); + if (count($answers) > 0) { + foreach ($answers as $answer) { + $jump['answerid'] = $answer->id; + $jump['jumpto'] = $answer->jumpto; + $jump['calculatedjump'] = $lesson->calculate_new_page_on_jump($page, $answer->jumpto); + // Special case, only applies to branch/end of branch. + if ($jump['calculatedjump'] == LESSON_RANDOMBRANCH) { + $jump['calculatedjump'] = lesson_unseen_branch_jump($lesson, $USER->id); + } + $jumps[] = $jump; + } + } else { + // Imported lessons from 1.x. + $jump['answerid'] = 0; + $jump['jumpto'] = $page->nextpageid; + $jump['calculatedjump'] = $lesson->calculate_new_page_on_jump($page, $page->nextpageid); + $jumps[] = $jump; + } + } + } + + $result = array( + 'jumps' => $jumps, + 'warnings' => $warnings, + ); + return $result; + } + + /** + * Describes the get_pages_possible_jumps return value. + * + * @return external_single_structure + * @since Moodle 3.3 + */ + public static function get_pages_possible_jumps_returns() { + return new external_single_structure( + array( + 'jumps' => new external_multiple_structure( + new external_single_structure( + array( + 'pageid' => new external_value(PARAM_INT, 'The page id'), + 'answerid' => new external_value(PARAM_INT, 'The answer id'), + 'jumpto' => new external_value(PARAM_INT, 'The jump (page id or type of jump)'), + 'calculatedjump' => new external_value(PARAM_INT, 'The real page id (or EOL) to jump'), + ), 'Jump for a page answer' + ) + ), + 'warnings' => new external_warnings(), + ) + ); + } } diff --git a/mod/lesson/db/services.php b/mod/lesson/db/services.php index 715c8d1952a..bc859c10d44 100644 --- a/mod/lesson/db/services.php +++ b/mod/lesson/db/services.php @@ -148,4 +148,12 @@ $functions = array( 'capabilities' => 'mod/lesson:viewreports', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_lesson_get_pages_possible_jumps' => array( + 'classname' => 'mod_lesson_external', + 'methodname' => 'get_pages_possible_jumps', + 'description' => 'Return all the possible jumps for the pages in a given lesson.', + 'type' => 'read', + 'capabilities' => 'mod/lesson:view', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/lesson/locallib.php b/mod/lesson/locallib.php index 721e56842a2..94963575503 100644 --- a/mod/lesson/locallib.php +++ b/mod/lesson/locallib.php @@ -3164,6 +3164,85 @@ class lesson extends lesson_base { return array($page, $lessoncontent); } + /** + * This returns a real page id to jump to (or LESSON_EOL) after processing page responses. + * + * @param lesson_page $page lesson page + * @param int $newpageid the new page id + * @return int the real page to jump to (or end of lesson) + * @since Moodle 3.3 + */ + public function calculate_new_page_on_jump(lesson_page $page, $newpageid) { + global $USER, $DB; + + $canmanage = $this->can_manage(); + + if (isset($USER->modattempts[$this->properties->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[$this->properties->id]->pageid == $page->id && $page->nextpageid == 0) { + // Remember, this session variable holds the pageid of the last page that the user saw. + $newpageid = LESSON_EOL; + } else { + $nretakes = $DB->count_records("lesson_grades", array("lessonid" => $this->properties->id, "userid" => $USER->id)); + $nretakes--; // Make sure we are looking at the right try. + $attempts = $DB->get_records("lesson_attempts", array("lessonid" => $this->properties->id, "userid" => $USER->id, "retry" => $nretakes), "timeseen", "id, pageid"); + $found = false; + $temppageid = 0; + // Make sure that the newpageid always defaults to something valid. + $newpageid = LESSON_EOL; + 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 == $page->id) { + $found = true; // If found current page. + $temppageid = $attempt->pageid; + } + } + } + } else if ($newpageid != LESSON_CLUSTERJUMP && $page->id != 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. + $newpage = $this->load_page($newpageid); + if ($overridenewpageid = $newpage->override_next_page($newpageid)) { + $newpageid = $overridenewpageid; + } + } else if ($newpageid == LESSON_UNSEENBRANCHPAGE) { + if ($canmanage) { + if ($page->nextpageid == 0) { + $newpageid = LESSON_EOL; + } else { + $newpageid = $page->nextpageid; + } + } else { + $newpageid = lesson_unseen_question_jump($this, $USER->id, $page->id); + } + } else if ($newpageid == LESSON_PREVIOUSPAGE) { + $newpageid = $page->prevpageid; + } else if ($newpageid == LESSON_RANDOMPAGE) { + $newpageid = lesson_random_question_jump($this, $page->id); + } else if ($newpageid == LESSON_CLUSTERJUMP) { + if ($canmanage) { + if ($page->nextpageid == 0) { // If teacher, go to next page. + $newpageid = LESSON_EOL; + } else { + $newpageid = $page->nextpageid; + } + } else { + $newpageid = $this->cluster_jump($page->id); + } + } else if ($newpageid == 0) { + $newpageid = $page->id; + } else if ($newpageid == LESSON_NEXTPAGE) { + $newpageid = $this->get_next_page($page->nextpageid); + } + + return $newpageid; + } + /** * Process page responses. * @@ -3171,9 +3250,6 @@ class lesson extends lesson_base { * @since Moodle 3.3 */ public function process_page_responses(lesson_page $page) { - global $USER, $DB; - - $canmanage = $this->can_manage(); $context = $this->get_context(); // Check the page has answers [MDL-25632]. @@ -3189,64 +3265,10 @@ class lesson extends lesson_base { if ($result->inmediatejump) { return $result; - } else if (isset($USER->modattempts[$this->properties->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[$this->properties->id]->pageid == $page->id && $page->nextpageid == 0) { - // Remember, this session variable holds the pageid of the last page that the user saw. - $result->newpageid = LESSON_EOL; - } else { - $nretakes = $DB->count_records("lesson_grades", array("lessonid" => $this->properties->id, "userid" => $USER->id)); - $nretakes--; // Make sure we are looking at the right try. - $attempts = $DB->get_records("lesson_attempts", array("lessonid" => $this->properties->id, "userid" => $USER->id, "retry" => $nretakes), "timeseen", "id, pageid"); - $found = false; - $temppageid = 0; - // Make sure that the newpageid always defaults to something valid. - $result->newpageid = LESSON_EOL; - 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; - } - } - } - } else if ($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 = $this->load_page($result->newpageid); - if ($newpageid = $newpage->override_next_page($result->newpageid)) { - $result->newpageid = $newpageid; - } - } else if ($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($this, $USER->id, $page->id); - } - } else if ($result->newpageid == LESSON_PREVIOUSPAGE) { - $result->newpageid = $page->prevpageid; - } else if ($result->newpageid == LESSON_RANDOMPAGE) { - $result->newpageid = lesson_random_question_jump($this, $page->id); - } else if ($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 = $this->cluster_jump($page->id); - } } + + $result->newpageid = $this->calculate_new_page_on_jump($page, $result->newpageid); + return $result; } @@ -3992,12 +4014,6 @@ abstract class lesson_page extends lesson_base { } } } - // 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) { - $result->newpageid = $this->lesson->get_next_page($this->properties->nextpageid); - } // Determine default feedback if necessary if (empty($result->response)) { diff --git a/mod/lesson/tests/external_test.php b/mod/lesson/tests/external_test.php index c86ff3bd605..6b145705737 100644 --- a/mod/lesson/tests/external_test.php +++ b/mod/lesson/tests/external_test.php @@ -1236,4 +1236,50 @@ class mod_lesson_external_testcase extends externallib_advanced_testcase { $this->setExpectedException('moodle_exception'); $result = mod_lesson_external::get_user_attempt($this->lesson->id, $this->teacher->id, 0); } + + /** + * Test get_pages_possible_jumps + */ + public function test_get_pages_possible_jumps() { + $this->setAdminUser(); + $result = mod_lesson_external::get_pages_possible_jumps($this->lesson->id); + $result = external_api::clean_returnvalue(mod_lesson_external::get_pages_possible_jumps_returns(), $result); + + $this->assertCount(0, $result['warnings']); + $this->assertCount(3, $result['jumps']); // 3 jumps, 2 from the question page and 1 from the content. + foreach ($result['jumps'] as $jump) { + if ($jump['answerid'] != 0) { + // Check only pages with answers. + if ($jump['jumpto'] == 0) { + $this->assertEquals($jump['pageid'], $jump['calculatedjump']); // 0 means to jump to current page. + } else { + // Question is configured to jump to next page if correct. + $this->assertEquals($this->page1->id, $jump['calculatedjump']); + } + } + } + } + + /** + * Test get_pages_possible_jumps when offline attemps are disabled for a normal user + */ + public function test_get_pages_possible_jumps_with_offlineattemps_disabled() { + $this->setUser($this->student->id); + $result = mod_lesson_external::get_pages_possible_jumps($this->lesson->id); + $result = external_api::clean_returnvalue(mod_lesson_external::get_pages_possible_jumps_returns(), $result); + $this->assertCount(0, $result['jumps']); + } + + /** + * Test get_pages_possible_jumps when offline attemps are enabled for a normal user + */ + public function test_get_pages_possible_jumps_with_offlineattemps_enabled() { + global $DB; + + $DB->set_field('lesson', 'allowofflineattempts', 1, array('id' => $this->lesson->id)); + $this->setUser($this->student->id); + $result = mod_lesson_external::get_pages_possible_jumps($this->lesson->id); + $result = external_api::clean_returnvalue(mod_lesson_external::get_pages_possible_jumps_returns(), $result); + $this->assertCount(3, $result['jumps']); + } } diff --git a/mod/lesson/version.php b/mod/lesson/version.php index e65884b5cb6..6c6bba2953c 100644 --- a/mod/lesson/version.php +++ b/mod/lesson/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016120516; // The current module version (Date: YYYYMMDDXX) +$plugin->version = 2016120517; // The current module version (Date: YYYYMMDDXX) $plugin->requires = 2016112900; // Requires this Moodle version $plugin->component = 'mod_lesson'; // Full name of the plugin (used for diagnostics) $plugin->cron = 0;