MDL-54862 quiz: Return question blocked status in WS
authorDani Palou <dani@moodle.com>
Wed, 27 Jul 2016 13:13:28 +0000 (15:13 +0200)
committerDani Palou <dani@moodle.com>
Wed, 27 Jul 2016 13:38:01 +0000 (15:38 +0200)
mod/quiz/classes/external.php
mod/quiz/tests/external_test.php
mod/quiz/upgrade.txt

index 2359578..2b71155 100644 (file)
@@ -863,6 +863,7 @@ class mod_quiz_external extends external_api {
      *
      * @return external_single_structure the question structure
      * @since  Moodle 3.1
+     * @since Moodle 3.2 blockedbyprevious parameter added.
      */
     private static function question_structure() {
         return new external_single_structure(
@@ -875,6 +876,8 @@ class mod_quiz_external extends external_api {
                 'number' => new external_value(PARAM_INT, 'question ordering number in the quiz', VALUE_OPTIONAL),
                 'state' => new external_value(PARAM_ALPHA, 'the state where the question is in', VALUE_OPTIONAL),
                 'status' => new external_value(PARAM_RAW, 'current formatted state of the question', VALUE_OPTIONAL),
+                'blockedbyprevious' => new external_value(PARAM_BOOL, 'whether the question is blocked by the previous question',
+                        VALUE_OPTIONAL),
                 'mark' => new external_value(PARAM_RAW, 'the mark awarded', VALUE_OPTIONAL),
                 'maxmark' => new external_value(PARAM_FLOAT, 'the maximum mark possible for this question attempt', VALUE_OPTIONAL),
             )
@@ -911,6 +914,7 @@ class mod_quiz_external extends external_api {
                 $question['number'] = $attemptobj->get_question_number($slot);
                 $question['state'] = (string) $attemptobj->get_question_state($slot);
                 $question['status'] = $attemptobj->get_question_status($slot, $displayoptions->correctness);
+                $question['blockedbyprevious'] = $attemptobj->is_blocked_by_previous_question($slot);
             }
             if ($displayoptions->marks >= question_display_options::MAX_ONLY) {
                 $question['maxmark'] = $attemptobj->get_question_attempt($slot)->get_max_mark();
index c106aca..9aa209e 100644 (file)
@@ -104,14 +104,16 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
      *
      * @param  boolean $startattempt whether to start a new attempt
      * @param  boolean $finishattempt whether to finish the new attempt
+     * @param  string $behaviour the quiz preferredbehaviour, defaults to 'deferredfeedback'.
      * @return array array containing the quiz, context and the attempt
      */
-    private function create_quiz_with_questions($startattempt = false, $finishattempt = false) {
+    private function create_quiz_with_questions($startattempt = false, $finishattempt = false, $behaviour = 'deferredfeedback') {
 
         // Create a new quiz with attempts.
         $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
         $data = array('course' => $this->course->id,
-                      'sumgrades' => 2);
+                      'sumgrades' => 2,
+                      'preferredbehaviour' => $behaviour);
         $quiz = $quizgenerator->create_instance($data);
         $context = context_module::instance($quiz->cmid);
 
@@ -929,6 +931,51 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
 
     }
 
+    /**
+     * Test get_attempt_data with blocked questions.
+     * @since 3.2
+     */
+    public function test_get_attempt_data_with_blocked_questions() {
+        global $DB;
+
+        // Create a new quiz with one attempt started and using immediatefeedback.
+        list($quiz, $context, $quizobj, $attempt, $attemptobj) = $this->create_quiz_with_questions(
+                true, false, 'immediatefeedback');
+
+        $quizobj = $attemptobj->get_quizobj();
+
+        // Make second question blocked by the first one.
+        $structure = $quizobj->get_structure();
+        $slots = $structure->get_slots();
+        $structure->update_question_dependency(end($slots)->id, true);
+
+        $quizobj->preload_questions();
+        $quizobj->load_questions();
+        $questions = $quizobj->get_questions();
+
+        $this->setUser($this->student);
+
+        // We receive one question per page.
+        $result = mod_quiz_external::get_attempt_data($attempt->id, 0);
+        $result = external_api::clean_returnvalue(mod_quiz_external::get_attempt_data_returns(), $result);
+
+        $this->assertEquals($attempt, (object) $result['attempt']);
+        $this->assertCount(1, $result['questions']);
+        $this->assertEquals(1, $result['questions'][0]['slot']);
+        $this->assertEquals(1, $result['questions'][0]['number']);
+        $this->assertEquals(false, $result['questions'][0]['blockedbyprevious']);
+
+        // Now try the last page.
+        $result = mod_quiz_external::get_attempt_data($attempt->id, 1);
+        $result = external_api::clean_returnvalue(mod_quiz_external::get_attempt_data_returns(), $result);
+
+        $this->assertEquals($attempt, (object) $result['attempt']);
+        $this->assertCount(1, $result['questions']);
+        $this->assertEquals(2, $result['questions'][0]['slot']);
+        $this->assertEquals(2, $result['questions'][0]['number']);
+        $this->assertEquals(true, $result['questions'][0]['blockedbyprevious']);
+    }
+
     /**
      * Test get_attempt_summary
      */
index 299f877..3568c52 100644 (file)
@@ -1,5 +1,11 @@
 This files describes API changes in the quiz code.
 
+=== 3.2 ===
+
+* External functions mod_quiz_external::get_attempt_data, mod_quiz_external::get_attempt_summary
+  and mod_quiz_external::get_attempt_review now return additional optional fields:
+   - blockedbyprevious: Whether a question is blocked by the previous question.
+
 === 3.1 ===
 
 * quiz_attempt::question_print_comment_fields() has been removed. It was broken