public function test_num_attempts_access_rule() { $quiz = new stdClass(); $quiz->decimalpoints = 2; $quiz->questiondecimalpoints = -1; $quiz->reviewattempt = 0x11110; $quiz->reviewcorrectness = 0x10000; $quiz->reviewmarks = 0x1110; $quiz->reviewspecificfeedback = 0x10000; $quiz->reviewgeneralfeedback = 0x1000; $quiz->reviewrightanswer = 0x100; $quiz->reviewoverallfeedback = 0x10; $options = mod_quiz_display_options::make_from_quiz($quiz, mod_quiz_display_options::DURING); $this->assertEqual(true, $options->attempt); $this->assertEqual(mod_quiz_display_options::VISIBLE, $options->correctness); $this->assertEqual(mod_quiz_display_options::MAX_ONLY, $options->marks); $this->assertEqual(2, $options->markdp); $quiz->questiondecimalpoints = 5; $options = mod_quiz_display_options::make_from_quiz($quiz, mod_quiz_display_options::IMMEDIATELY_AFTER); $this->assertEqual(mod_quiz_display_options::MARK_AND_MAX, $options->marks); $this->assertEqual(mod_quiz_display_options::VISIBLE, $options->generalfeedback); $this->assertEqual(mod_quiz_display_options::HIDDEN, $options->feedback); $this->assertEqual(5, $options->markdp); $options = mod_quiz_display_options::make_from_quiz($quiz, mod_quiz_display_options::LATER_WHILE_OPEN); $this->assertEqual(mod_quiz_display_options::VISIBLE, $options->rightanswer); $this->assertEqual(mod_quiz_display_options::HIDDEN, $options->generalfeedback); $options = mod_quiz_display_options::make_from_quiz($quiz, mod_quiz_display_options::AFTER_CLOSE); $this->assertEqual(mod_quiz_display_options::VISIBLE, $options->overallfeedback); $this->assertEqual(mod_quiz_display_options::HIDDEN, $options->rightanswer); }
/** * Should the grades be displayed in this report. That depends on the quiz * display options, and whether the quiz is graded. * @param object $quiz the quiz settings. * @return bool */ protected function should_show_grades($quiz) { if (!is_null($this->showgrades)) { return $this->showgrades; } if ($quiz->timeclose && time() > $quiz->timeclose) { $when = mod_quiz_display_options::AFTER_CLOSE; } else { $when = mod_quiz_display_options::LATER_WHILE_OPEN; } $reviewoptions = mod_quiz_display_options::make_from_quiz($quiz, $when); $this->showgrades = quiz_has_grades($quiz) && ($reviewoptions->marks >= question_display_options::MARK_AND_MAX || has_capability('moodle/grade:viewhidden', $this->context)); return $this->showgrades; }
/** * Wrapper that the correct mod_quiz_display_options for this quiz at the * moment. * * @return question_display_options the render options for this user on this attempt. */ public function get_display_options($reviewing) { if ($reviewing) { if (is_null($this->reviewoptions)) { $this->reviewoptions = quiz_get_review_options($this->get_quiz(), $this->attempt, $this->quizobj->get_context()); if ($this->is_own_preview()) { // It should always be possible for a teacher to review their // own preview irrespective of the review options settings. $this->reviewoptions->attempt = true; } } return $this->reviewoptions; } else { $options = mod_quiz_display_options::make_from_quiz($this->get_quiz(), mod_quiz_display_options::DURING); $options->flags = quiz_get_flag_option($this->attempt, $this->quizobj->get_context()); return $options; } }
/** * Make some text into a link to review the quiz, if that is appropriate. * * @param string $linktext some text. * @param object $attempt the attempt object * @return string some HTML, the $linktext either unmodified or wrapped in a * link to the review page. */ public function make_review_link($attempt, $reviewoptions, $output) { // If the attempt is still open, don't link. if (in_array($attempt->state, array(quiz_attempt::IN_PROGRESS, quiz_attempt::OVERDUE))) { return $output->no_review_message(''); } $when = quiz_attempt_state($this->quizobj->get_quiz(), $attempt); $reviewoptions = mod_quiz_display_options::make_from_quiz( $this->quizobj->get_quiz(), $when); if (!$reviewoptions->attempt) { return $output->no_review_message($this->quizobj->cannot_review_message($when, true)); } else { return $output->review_link($this->quizobj->review_url($attempt->id), $this->attempt_must_be_in_popup(), $this->get_popup_options()); } }
/** * Wrapper that the correct mod_quiz_display_options for this quiz at the * moment. * * @return question_display_options the render options for this user on this attempt. */ public function get_display_options($reviewing) { if ($reviewing) { if (is_null($this->reviewoptions)) { $this->reviewoptions = quiz_get_review_options($this->get_quiz(), $this->attempt, $this->quizobj->get_context()); } return $this->reviewoptions; } else { $options = mod_quiz_display_options::make_from_quiz($this->get_quiz(), mod_quiz_display_options::DURING); $options->flags = quiz_get_flag_option($this->attempt, $this->quizobj->get_context()); return $options; } }
/** * Combines the review options from a number of different quiz attempts. * Returns an array of two ojects, so the suggested way of calling this * funciton is: * list($someoptions, $alloptions) = quiz_get_combined_reviewoptions(...) * * @param object $quiz the quiz instance. * @param array $attempts an array of attempt objects. * @param $context the roles and permissions context, * normally the context for the quiz module instance. * * @return array of two options objects, one showing which options are true for * at least one of the attempts, the other showing which options are true * for all attempts. */ function quiz_get_combined_reviewoptions($quiz, $attempts) { $fields = array('feedback', 'generalfeedback', 'rightanswer', 'overallfeedback'); $someoptions = new stdClass(); $alloptions = new stdClass(); foreach ($fields as $field) { $someoptions->$field = false; $alloptions->$field = true; } $someoptions->marks = question_display_options::HIDDEN; $alloptions->marks = question_display_options::MARK_AND_MAX; foreach ($attempts as $attempt) { $attemptoptions = mod_quiz_display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt)); foreach ($fields as $field) { $someoptions->$field = $someoptions->$field || $attemptoptions->$field; $alloptions->$field = $alloptions->$field && $attemptoptions->$field; } $someoptions->marks = max($someoptions->marks, $attemptoptions->marks); $alloptions->marks = min($alloptions->marks, $attemptoptions->marks); } return array($someoptions, $alloptions); }
/** * Should the grades be displayed in this report. That depends on the quiz * display options, and whether the quiz is graded. * @param object $quiz the quiz settings. * @param context $context the quiz context. * @return bool */ function quiz_report_should_show_grades($quiz, context $context) { if ($quiz->timeclose && time() > $quiz->timeclose) { $when = mod_quiz_display_options::AFTER_CLOSE; } else { $when = mod_quiz_display_options::LATER_WHILE_OPEN; } $reviewoptions = mod_quiz_display_options::make_from_quiz($quiz, $when); return quiz_has_grades($quiz) && ($reviewoptions->marks >= question_display_options::MARK_AND_MAX || has_capability('moodle/grade:viewhidden', $context)); }
/** * Create or update the grade item for given quiz * * @category grade * @param object $quiz object with extra cmidnumber * @param mixed $grades optional array/object of grade(s); 'reset' means reset grades in gradebook * @return int 0 if ok, error code otherwise */ function quiz_grade_item_update($quiz, $grades = null) { global $CFG, $OUTPUT; require_once($CFG->dirroot . '/mod/quiz/locallib.php'); require_once($CFG->libdir . '/gradelib.php'); if (array_key_exists('cmidnumber', $quiz)) { // May not be always present. $params = array('itemname' => $quiz->name, 'idnumber' => $quiz->cmidnumber); } else { $params = array('itemname' => $quiz->name); } if ($quiz->grade > 0) { $params['gradetype'] = GRADE_TYPE_VALUE; $params['grademax'] = $quiz->grade; $params['grademin'] = 0; } else { $params['gradetype'] = GRADE_TYPE_NONE; } // What this is trying to do: // 1. If the quiz is set to not show grades while the quiz is still open, // and is set to show grades after the quiz is closed, then create the // grade_item with a show-after date that is the quiz close date. // 2. If the quiz is set to not show grades at either of those times, // create the grade_item as hidden. // 3. If the quiz is set to show grades, create the grade_item visible. $openreviewoptions = mod_quiz_display_options::make_from_quiz($quiz, mod_quiz_display_options::LATER_WHILE_OPEN); $closedreviewoptions = mod_quiz_display_options::make_from_quiz($quiz, mod_quiz_display_options::AFTER_CLOSE); if ($openreviewoptions->marks < question_display_options::MARK_AND_MAX && $closedreviewoptions->marks < question_display_options::MARK_AND_MAX) { $params['hidden'] = 1; } else if ($openreviewoptions->marks < question_display_options::MARK_AND_MAX && $closedreviewoptions->marks >= question_display_options::MARK_AND_MAX) { if ($quiz->timeclose) { $params['hidden'] = $quiz->timeclose; } else { $params['hidden'] = 1; } } else { // Either // a) both open and closed enabled // b) open enabled, closed disabled - we can not "hide after", // grades are kept visible even after closing. $params['hidden'] = 0; } if ($grades === 'reset') { $params['reset'] = true; $grades = null; } $gradebook_grades = grade_get_grades($quiz->course, 'mod', 'quiz', $quiz->id); if (!empty($gradebook_grades->items)) { $grade_item = $gradebook_grades->items[0]; if ($grade_item->locked) { // NOTE: this is an extremely nasty hack! It is not a bug if this confirmation fails badly. --skodak. $confirm_regrade = optional_param('confirm_regrade', 0, PARAM_INT); if (!$confirm_regrade) { $message = get_string('gradeitemislocked', 'grades'); $back_link = $CFG->wwwroot . '/mod/quiz/report.php?q=' . $quiz->id . '&mode=overview'; $regrade_link = qualified_me() . '&confirm_regrade=1'; echo $OUTPUT->box_start('generalbox', 'notice'); echo '<p>'. $message .'</p>'; echo $OUTPUT->container_start('buttons'); echo $OUTPUT->single_button($regrade_link, get_string('regradeanyway', 'grades')); echo $OUTPUT->single_button($back_link, get_string('cancel')); echo $OUTPUT->container_end(); echo $OUTPUT->box_end(); return GRADE_UPDATE_ITEM_LOCKED; } } } return grade_update('mod/quiz', $quiz->course, 'mod', 'quiz', $quiz->id, 0, $grades, $params); }
/** * Combines the review options from a number of different quiz attempts. * Returns an array of two ojects, so the suggested way of calling this * funciton is: * list($someoptions, $alloptions) = quiz_get_combined_reviewoptions(...) * * @param object $quiz the quiz instance. * @param array $attempts an array of attempt objects. * * @return array of two options objects, one showing which options are true for * at least one of the attempts, the other showing which options are true * for all attempts. */ function quiz_get_combined_reviewoptions($quiz, $attempts) { $fields = array('feedback', 'generalfeedback', 'rightanswer', 'overallfeedback'); $someoptions = new stdClass(); $alloptions = new stdClass(); foreach ($fields as $field) { $someoptions->{$field} = false; $alloptions->{$field} = true; } $someoptions->marks = question_display_options::HIDDEN; $alloptions->marks = question_display_options::MARK_AND_MAX; // This shouldn't happen, but we need to prevent reveal information. if (empty($attempts)) { return array($someoptions, $someoptions); } foreach ($attempts as $attempt) { $attemptoptions = mod_quiz_display_options::make_from_quiz($quiz, quiz_attempt_state($quiz, $attempt)); foreach ($fields as $field) { $someoptions->{$field} = $someoptions->{$field} || $attemptoptions->{$field}; $alloptions->{$field} = $alloptions->{$field} && $attemptoptions->{$field}; } $someoptions->marks = max($someoptions->marks, $attemptoptions->marks); $alloptions->marks = min($alloptions->marks, $attemptoptions->marks); } return array($someoptions, $alloptions); }
/** * Make some text into a link to review the quiz, if that is appropriate. * * @param string $linktext some text. * @param object $attempt the attempt object * @return string some HTML, the $linktext either unmodified or wrapped in a * link to the review page. */ public function make_review_link($attempt, $canpreview, $reviewoptions) { global $CFG; // If review of responses is not allowed, or the attempt is still open, don't link. if (!$attempt->timefinish) { return ''; } $when = quiz_attempt_state($this->_quizobj->get_quiz(), $attempt); $reviewoptions = mod_quiz_display_options::make_from_quiz( $this->_quizobj->get_quiz(), $when); if (!$reviewoptions->attempt) { $message = $this->cannot_review_message($when, true); if ($message) { return '<span class="noreviewmessage">' . $message . '</span>'; } else { return ''; } } $linktext = get_string('review', 'quiz'); // It is OK to link, does it need to be in a secure window? if ($this->securewindow_required($canpreview)) { return $this->_securewindowrule->make_review_link($linktext, $attempt->id); } else { return '<a href="' . $this->_quizobj->review_url($attempt->id) . '" title="' . get_string('reviewthisattempt', 'quiz') . '">' . $linktext . '</a>'; } }
/** * Make some text into a link to review the quiz, if that is appropriate. * * @param string $linktext some text. * @param object $attempt the attempt object * @return string some HTML, the $linktext either unmodified or wrapped in a * link to the review page. */ public function make_review_link($attempt, $reviewoptions, $output) { // If review of responses is not allowed, or the attempt is still open, don't link. if (!$attempt->timefinish) { return $output->no_review_message(''); } $when = quiz_attempt_state($this->quizobj->get_quiz(), $attempt); $reviewoptions = mod_quiz_display_options::make_from_quiz( $this->quizobj->get_quiz(), $when); if (!$reviewoptions->attempt) { return $output->no_review_message($this->quizobj->cannot_review_message($when, true)); } else { return $output->review_link($this->quizobj->review_url($attempt->id), $this->attempt_must_be_in_popup(), $this->get_popup_options()); } }