abstract class QuizQuestionResponse in OG Quiz 7
Each question type must store its own response data and be able to calculate a score for that data.
Hierarchy
- class \QuizQuestionResponse
Expanded class hierarchy of QuizQuestionResponse
File
- includes/
og_quiz_question.php, line 743 - Classes used in the Quiz Question module.
View source
abstract class QuizQuestionResponse {
// Result id
protected $rid = 0;
protected $is_correct = FALSE;
protected $evaluated = TRUE;
// The question node(not a quiz question instance)
public $question = NULL;
protected $answer = NULL;
protected $score;
public $is_skipped;
public $is_doubtful;
/**
* Create a new user response.
*
* @param $result_id
* The result ID for the user's result set. There is one result ID per time
* the user takes a quiz.
* @param $question_node
* The question node.
* @param $answer
* The answer (dependent on question type).
*/
public function __construct($result_id, stdClass $question_node, $answer = NULL) {
$this->rid = $result_id;
$this->question = $question_node;
$this->answer = $answer;
$result = db_query('SELECT is_skipped, is_doubtful FROM {quiz_node_results_answers}
WHERE result_id = :result_id AND question_nid = :question_nid AND question_vid = :question_vid', array(
':result_id' => $result_id,
':question_nid' => $question_node->nid,
':question_vid' => $question_node->vid,
))
->fetch();
if (is_object($result)) {
$this->is_doubtful = $result->is_doubtful;
$this->is_skipped = $result->is_skipped;
}
}
/**
* Used to refresh this instances question node in case drupal has changed it.
*
* @param $newNode
* Question node
*/
public function refreshQuestionNode($newNode) {
$this->question = $newNode;
}
/**
* Indicate whether the response has been evaluated (scored) yet.
* Questions that require human scoring (e.g. essays) may need to manually
* toggle this.
*/
public function isEvaluated() {
return (bool) $this->evaluated;
}
/**
* Check to see if the answer is marked as correct.
*
* This default version returns TRUE iff the score is equal to the maximum possible score.
*/
function isCorrect() {
return $this
->getMaxScore() == $this
->getScore();
}
/**
* Helper function to determine if a user has access to score a quiz.
*
* @param $quiz_creator
* uid of the quiz creator.
*
* @return bool
*/
public function quizContextAccessToScore($quiz_creator = NULL) {
// Must we check this node, or the parent quiz ?
if (!isset($this->checkWhat)) {
if (isset($this->question->nid) && og_is_group_content_type('node', $this->question->type)) {
$groups = og_get_entity_groups('node', $this->node);
if (!empty($groups)) {
$this->checkWhat = 'self';
}
}
// If empty, check the parent quiz.
if (!isset($this->checkWhat)) {
// Try fetching the parent quiz, if any.
$quiz = $this
->getParentQuiz();
if (isset($quiz)) {
$this->checkWhat = 'parent';
}
else {
// Use default permissions.
$this->checkWhat = 'none';
}
}
}
if ($this->checkWhat != 'none') {
if ($this->checkWhat == 'parent') {
$node = $this
->getParentQuiz();
}
else {
$node = clone $this->question;
}
if ($quiz_creator == NULL && ($quiz = quiz_get_quiz_from_menu())) {
$quiz_creator = $quiz->uid;
}
if (!($access = og_quiz_ogs_access($node, array(
'score taken quiz answer',
'score taken quiz answer',
)))) {
$access = og_quiz_ogs_access($node, 'score own quiz');
if ($access) {
global $user;
$access = $access && $user->uid == $quiz_creator;
}
}
}
return isset($access) ? $access : quiz_access_to_score($quiz_creator);
}
/**
* Fetch the parent quiz.
*
* @return stdClass|null
*/
public function getParentQuiz() {
if (isset($this->question->nid)) {
$quiz = db_select('quiz_node_relationship', 'r')
->fields('r', array(
'parent_nid',
'parent_vid',
))
->condition('child_nid', $this->question->nid)
->condition('child_vid', $this->question->vid)
->execute()
->fetchObject();
if (isset($quiz->nid)) {
return node_load($quiz->nid, $quiz->vid);
}
}
return NULL;
}
/**
* Returns stored score if it exists, if not the score is calculated and returned.
*
* @param $weight_adjusted
* If the returned score shall be adjusted according to the max_score the question has in a quiz
* @return
* Score(int)
*/
function getScore($weight_adjusted = TRUE) {
if ($this->is_skipped) {
return 0;
}
if (!isset($this->score)) {
$this->score = $this
->score();
}
if (isset($this->question->score_weight) && $weight_adjusted) {
return round($this->score * $this->question->score_weight);
}
return $this->score;
}
/**
* Returns stored max score if it exists, if not the max score is calculated and returned.
*
* @param $weight_adjusted
* If the returned max score shall be adjusted according to the max_score the question has in a quiz
* @return
* Max score(int)
*/
public function getMaxScore($weight_adjusted = TRUE) {
if (!isset($this->question->max_score)) {
$this->question->max_score = 1;
}
if (isset($this->question->score_weight) && $weight_adjusted) {
return round($this->question->max_score * $this->question->score_weight);
}
return $this->question->max_score;
}
/**
* Represent the response as a stdClass object.
*
* Convert data to an object that has the following properties:
* - $score
* - $rid
* - $nid
* - $vid
* - $is_correct
*/
function toBareObject() {
$obj = new stdClass();
$obj->score = $this
->getScore();
// This can be 0 for unscored.
$obj->nid = $this->question->nid;
$obj->vid = $this->question->vid;
$obj->rid = $this->rid;
$obj->is_correct = (int) $this
->isCorrect();
$obj->is_evaluated = $this
->isEvaluated();
$obj->is_skipped = 0;
$obj->is_doubtful = isset($_POST['is_doubtful']) ? $_POST['is_doubtful'] : 0;
$obj->is_valid = $this
->isValid();
return $obj;
}
/**
* Validates response from a quiz taker. If the response isn't valid the quiz taker won't be allowed to proceed.
*
* @return
* True if the response is valid.
* False otherwise
*/
public function isValid() {
return TRUE;
}
/**
* Get data suitable for reporting a user's score on the question.
* This expects an object with the following attributes:
*
* answer_id; // The answer ID
* answer; // The full text of the answer
* is_evaluated; // 0 if the question has not been evaluated, 1 if it has
* score; // The score the evaluator gave the user; this should be 0 if is_evaluated is 0.
* question_vid
* question_nid
* result_id
*/
public function getReport() {
// Basically, we encode internal information in a
// legacy array format for Quiz.
$report = array(
'answer_id' => 0,
// <-- Stupid vestige of multichoice.
'answer' => $this->answer,
'is_evaluated' => $this
->isEvaluated(),
'is_correct' => $this
->isCorrect(),
'score' => $this
->getScore(),
'question_vid' => $this->question->vid,
'question_nid' => $this->question->nid,
'result_id' => $this->rid,
);
return $report;
}
/**
* Creates the report form for the admin pages, and for when a user gets feedback after answering questions.
*
* The report is a form to allow editing scores and the likes while viewing the report form
*
* @param $showpoints
* @param $showfeedback
* @param $allow_scoring
* @return $form
* Drupal form array
*/
public function getReportForm($showpoints = TRUE, $showfeedback = TRUE, $allow_scoring = FALSE) {
/*
* Add general data, and data from the question type implementation
*/
$form = array();
$form['nid'] = array(
'#type' => 'value',
'#value' => $this->question->nid,
);
$form['vid'] = array(
'#type' => 'value',
'#value' => $this->question->vid,
);
$form['rid'] = array(
'#type' => 'value',
'#value' => $this->rid,
);
if ($submit = $this
->getReportFormSubmit($showpoints, $showfeedback, $allow_scoring)) {
$form['submit'] = array(
'#type' => 'value',
'#value' => $submit,
);
}
if ($validate = $this
->getReportFormValidate($showpoints, $showfeedback, $allow_scoring)) {
$form['validate'] = array(
'#type' => 'value',
'#value' => $validate,
);
}
$form['question'] = $this
->getReportFormQuestion($showpoints, $showfeedback);
$form['score'] = $this
->getReportFormScore($showpoints, $showfeedback, $allow_scoring);
$form['answer_feedback'] = $this
->getReportFormAnswerFeedback($showpoints, $showfeedback, $allow_scoring);
$form['max_score'] = array(
'#type' => 'value',
'#value' => $this
->getMaxScore(),
);
$form['response'] = $this
->getReportFormResponse($showpoints, $showfeedback, $allow_scoring);
$form['#theme'] = $this
->getReportFormTheme($showpoints, $showfeedback);
$form['#is_correct'] = $this
->isCorrect();
$form['#is_evaluated'] = $this
->isEvaluated();
$form['#is_skipped'] = $this->is_skipped;
$form['#is_doubtful'] = $this->is_doubtful;
return $form;
}
/**
* get the question part of the reportForm
*
* @param $showpoints
* @param $showfeedback
* @return
* FAPI form array holding the question
*/
public function getReportFormQuestion($showpoints = TRUE, $showfeedback = TRUE) {
$node = node_load($this->question->nid);
$items = field_get_items('node', $node, 'body');
return field_view_value('node', $node, 'body', $items[0]);
}
/**
* Get the response part of the report form
*
* @param $showpoints
* @param $showfeedback
* @param $allow_scoring
* @return
* FAPI form array holding the response part
*/
public function getReportFormResponse($showpoints = TRUE, $showfeedback = TRUE, $allow_scoring = FALSE) {
return array(
'#markup' => '',
);
}
/**
* Get the score part of the report form
*
* @param $showpoints
* @param $showfeedback
* @param $allow_scoring
* @return
* FAPI form array holding the score part
*/
public function getReportFormScore($showpoints = TRUE, $showfeedback = TRUE, $allow_scoring = FALSE) {
return array(
'#markup' => '<span class="quiz-report-score">' . $this
->getScore() . '</span>',
);
}
public function getReportFormAnswerFeedback($showpoints, $showfeedback, $allow_scoring) {
return FALSE;
}
/**
* Get the submit function for the reportForm
*
* @return
* Submit function as a string, or FALSE if no submit function
*/
public function getReportFormSubmit($showfeedback = TRUE, $showpoints = TRUE, $allow_scoring = FALSE) {
return FALSE;
}
/**
* Get the validate function for the reportForm
*
* @return
* Validate function as a string, or FALSE if no validate function
*/
public function getReportFormValidate($showfeedback = TRUE, $showpoints = TRUE, $allow_scoring = FALSE) {
return FALSE;
}
/**
* Get the theme key for the reportForm
*
* @return
* Theme key as a string, or FALSE if no submit function
*/
public function getReportFormTheme($showfeedback = TRUE, $showpoints = TRUE) {
return FALSE;
}
/**
* Saves the quiz result. This is not used when a question is skipped!
*/
public function saveResult() {
$this->is_skipped = FALSE;
$this
->save();
}
/**
* Utility function that returns the format of the node body
*/
protected function getFormat() {
$body = field_get_items('node', $this->question, 'body');
return $body ? $body[0]['format'] : NULL;
}
/**
* Save the current response.
*/
public abstract function save();
/**
* Delete the response.
*/
public abstract function delete();
/**
* Calculate the score for the response.
*/
public abstract function score();
/**
* Get the user's response.
*/
public abstract function getResponse();
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
QuizQuestionResponse:: |
protected | property | ||
QuizQuestionResponse:: |
protected | property | ||
QuizQuestionResponse:: |
protected | property | ||
QuizQuestionResponse:: |
public | property | ||
QuizQuestionResponse:: |
public | property | ||
QuizQuestionResponse:: |
public | property | ||
QuizQuestionResponse:: |
protected | property | ||
QuizQuestionResponse:: |
protected | property | 1 | |
QuizQuestionResponse:: |
abstract public | function | Delete the response. | 1 |
QuizQuestionResponse:: |
protected | function | Utility function that returns the format of the node body | |
QuizQuestionResponse:: |
public | function | Returns stored max score if it exists, if not the max score is calculated and returned. | |
QuizQuestionResponse:: |
public | function | Fetch the parent quiz. | |
QuizQuestionResponse:: |
public | function | Get data suitable for reporting a user's score on the question. This expects an object with the following attributes: | |
QuizQuestionResponse:: |
public | function | Creates the report form for the admin pages, and for when a user gets feedback after answering questions. | |
QuizQuestionResponse:: |
public | function | 1 | |
QuizQuestionResponse:: |
public | function | get the question part of the reportForm | |
QuizQuestionResponse:: |
public | function | Get the response part of the report form | 1 |
QuizQuestionResponse:: |
public | function | Get the score part of the report form | 1 |
QuizQuestionResponse:: |
public | function | Get the submit function for the reportForm | 1 |
QuizQuestionResponse:: |
public | function | Get the theme key for the reportForm | |
QuizQuestionResponse:: |
public | function | Get the validate function for the reportForm | 1 |
QuizQuestionResponse:: |
abstract public | function | Get the user's response. | 1 |
QuizQuestionResponse:: |
function | Returns stored score if it exists, if not the score is calculated and returned. | ||
QuizQuestionResponse:: |
function | Check to see if the answer is marked as correct. | ||
QuizQuestionResponse:: |
public | function | Indicate whether the response has been evaluated (scored) yet. Questions that require human scoring (e.g. essays) may need to manually toggle this. | |
QuizQuestionResponse:: |
public | function | Validates response from a quiz taker. If the response isn't valid the quiz taker won't be allowed to proceed. | 1 |
QuizQuestionResponse:: |
public | function | Helper function to determine if a user has access to score a quiz. | |
QuizQuestionResponse:: |
public | function | Used to refresh this instances question node in case drupal has changed it. | |
QuizQuestionResponse:: |
abstract public | function | Save the current response. | 1 |
QuizQuestionResponse:: |
public | function | Saves the quiz result. This is not used when a question is skipped! | |
QuizQuestionResponse:: |
abstract public | function | Calculate the score for the response. | 1 |
QuizQuestionResponse:: |
function | Represent the response as a stdClass object. | ||
QuizQuestionResponse:: |
public | function | Create a new user response. | 1 |