diff --git a/lib/questionlib.php b/lib/questionlib.php
index cc962a76146..1d205299110 100644
--- a/lib/questionlib.php
+++ b/lib/questionlib.php
@@ -561,6 +561,7 @@ function get_question_states(&$questions, $cmoptions, $attempt) {
$states[$i]->last_graded = $gradedstates[$i];
} else {
$states[$i]->last_graded = clone($states[$i]);
+ $states[$i]->last_graded->responses = array('' => '');
}
} else {
// Create a new state object
@@ -745,18 +746,26 @@ function question_state_is_closed($state) {
/**
-* Extracts responses from submitted form
-*
-* TODO: Finish documenting this
-* @return array array of action objects, indexed by question ids.
-* @param array $questions an array containing at least all questions that are used on the form
-* @param array $responses
-* @param integer $defaultevent
-*/
-function question_extract_responses($questions, $responses, $defaultevent) {
+ * Extracts responses from submitted form
+ *
+ * This can extract the responses given to one or several questions present on a page
+ * It returns an array with one entry for each question, indexed by question id
+ * Each entry is an object with the properties
+ * ->event The event that has triggered the submission. This is determined by which button
+ * the user has pressed.
+ * ->responses An array holding the responses to an individual question, indexed by the
+ * name of the corresponding form element.
+ * ->timestamp A unix timestamp
+ * @return array array of action objects, indexed by question ids.
+ * @param array $questions an array containing at least all questions that are used on the form
+ * @param array $formdata the data submitted by the form on the question page
+ * @param integer $defaultevent the event type used if no 'mark' or 'validate' is submitted
+ */
+function question_extract_responses($questions, $formdata, $defaultevent=QUESTION_EVENTSAVE) {
+ $time = time();
$actions = array();
- foreach ($responses as $key => $response) {
+ foreach ($formdata as $key => $response) {
// Get the question id from the response name
if (false !== ($quid = question_get_id_from_name_prefix($key))) {
// check if this is a valid id
@@ -773,7 +782,7 @@ function question_extract_responses($questions, $responses, $defaultevent) {
// Check for question validate and mark buttons & set events
if ($key === 'validate') {
$actions[$quid]->event = QUESTION_EVENTVALIDATE;
- } else if ($key === 'mark') {
+ } else if ($key === 'submit') {
$actions[$quid]->event = QUESTION_EVENTSUBMIT;
} else {
$actions[$quid]->event = $defaultevent;
@@ -781,6 +790,9 @@ function question_extract_responses($questions, $responses, $defaultevent) {
// Update the state with the new response
$actions[$quid]->responses[$key] = $response;
+
+ // Set the timestamp
+ $actions[$quid]->timestamp = $time;
}
}
return $actions;
@@ -1182,7 +1194,12 @@ function question_get_id_from_name_prefix($name) {
}
/**
- * TODO: document this
+ * Returns the unique id for a new attempt
+ *
+ * Every module can keep their own attempts table with their own sequential ids but
+ * the question code needs to also have a unique id by which to identify all these
+ * attempts. Hence a module, when creating a new attempt, calls this function and
+ * stores the return value in the 'uniqueid' field of its attempts table.
*/
function question_new_attempt_uniqueid() {
global $CFG;
@@ -1193,11 +1210,16 @@ function question_new_attempt_uniqueid() {
/// FUNCTIONS THAT SIMPLY WRAP QUESTIONTYPE METHODS //////////////////////////////////
-/**
-* Prints a question
-*
-* Simply calls the question type specific print_question() method.
-*/
+ /**
+ * Prints a question
+ *
+ * Simply calls the question type specific print_question() method.
+ * @param object $question The question to be rendered.
+ * @param object $state The state to render the question in.
+ * @param integer $number The number for this question.
+ * @param object $cmoptions The options specified by the course module
+ * @param object $options An object specifying the rendering options.
+ */
function print_question(&$question, &$state, $number, $cmoptions, $options=null) {
global $QTYPES;
diff --git a/mod/quiz/attempt.php b/mod/quiz/attempt.php
index a1b24eebf1d..4ead6d79d29 100644
--- a/mod/quiz/attempt.php
+++ b/mod/quiz/attempt.php
@@ -469,7 +469,7 @@
$pagequestions = explode(',', $pagelist);
$number = quiz_first_questionnumber($attempt->layout, $pagelist);
foreach ($pagequestions as $i) {
- $options = quiz_get_renderoptions($quiz, $states[$i]);
+ $options = quiz_get_renderoptions($quiz->review, $states[$i]);
// Print the question
if ($i > 0) {
echo " \n";
diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php
index 952a8385831..3a2b659bc73 100644
--- a/mod/quiz/locallib.php
+++ b/mod/quiz/locallib.php
@@ -479,21 +479,24 @@ function quiz_get_question_review($quiz, $question) {
/**
-* Determine render options
-*/
-function quiz_get_renderoptions($cmoptions, $state) {
+ * Determine render options
+ *
+ * @param int $reviewoptions
+ * @param object $state
+ */
+function quiz_get_renderoptions($reviewoptions, $state) {
// Show the question in readonly (review) mode if the question is in
// the closed state
- $options->readonly = QUESTION_EVENTCLOSE === $state->event;
+ $options->readonly = question_state_is_closed($state);
// Show feedback once the question has been graded (if allowed by the quiz)
- $options->feedback = ($state->event == QUESTION_EVENTGRADE) && ($cmoptions->review & QUIZ_REVIEW_FEEDBACK & QUIZ_REVIEW_IMMEDIATELY);
+ $options->feedback = question_state_is_graded($state) && ($reviewoptions & QUIZ_REVIEW_FEEDBACK & QUIZ_REVIEW_IMMEDIATELY);
// Show validation only after a validation event
$options->validation = QUESTION_EVENTVALIDATE === $state->event;
// Show correct responses in readonly mode if the quiz allows it
- $options->correct_responses = $options->readonly && ($cmoptions->review & QUIZ_REVIEW_ANSWERS & QUIZ_REVIEW_IMMEDIATELY);
+ $options->correct_responses = $options->readonly && ($reviewoptions & QUIZ_REVIEW_ANSWERS & QUIZ_REVIEW_IMMEDIATELY);
// Always show responses and scores
$options->responses = true;
diff --git a/question/questiontypes/questiontype.php b/question/questiontypes/questiontype.php
index 3ea06b474f6..be65d50c1ce 100644
--- a/question/questiontypes/questiontype.php
+++ b/question/questiontypes/questiontype.php
@@ -422,7 +422,6 @@ class default_questiontype {
* submitted responses and the interactions. The default implementation calls
* various other methods to print each of these parts and most question types
* will just override those methods.
- * @todo Use CSS stylesheet
* @param object $question The question to be rendered. Question type
* specific information is included. The
* maximum possible grade is in ->maxgrade. The name
@@ -624,7 +623,7 @@ class default_questiontype {
* This function prints the submit button(s) for the question in the
* given state. The name of any button created will be prefixed with the
* unique prefix for the question in $question->name_prefix. The suffix
- * 'mark' is reserved for the single question mark button and the suffix
+ * 'submit' is reserved for the single question submit button and the suffix
* 'validate' is reserved for the single question validate button (for
* question types which support it). Other suffixes will result in a response
* of that name in $state->responses which the printing and grading methods
@@ -647,7 +646,7 @@ class default_questiontype {
if (($cmoptions->optionflags & QUESTION_ADAPTIVE) and !$options->readonly) {
echo '';
diff --git a/question/questiontypes/rqp/questiontype.php b/question/questiontypes/rqp/questiontype.php
index 22135ee03ea..f60510368bc 100644
--- a/question/questiontypes/rqp/questiontype.php
+++ b/question/questiontypes/rqp/questiontype.php
@@ -352,7 +352,7 @@ class question_rqp_qtype extends default_questiontype {
if ($cmoptions->optionflags & QUESTION_ADAPTIVE) {
echo '';
}