quiz.pages.inc in Quiz 6.2
User pages.
File
quiz.pages.incView source
<?php
/**
* User pages.
* @file
*/
/*
* Quiz Results User.
*/
function quiz_user_results($result_id) {
global $user;
$sql = 'SELECT qnp.nid, qnrs.uid
FROM {quiz_node_properties} qnp
INNER JOIN {quiz_node_results} qnrs
WHERE qnrs.nid = qnp.nid AND qnrs.result_id = %d';
$result = db_fetch_object(db_query($sql, $result_id));
if ($result->nid) {
// User can view own results (quiz_menu sets access to 'own results').
// User with role 'user results' can view other user's results.
if ($result->uid != $user->uid && !user_access('user results')) {
drupal_access_denied();
return;
}
$quiz = node_load($result->nid);
$questions = _quiz_get_answers($result_id);
$score = quiz_calculate_score($quiz, $result_id);
$summary = _quiz_get_summary_text($quiz, $score);
return theme('quiz_user_summary', $quiz, $questions, $score, $summary);
}
else {
drupal_not_found();
}
}
/**
* Displays all the quizzes the user has taken part in.
*
* @return
* HTML output for page.
*/
function quiz_get_user_results($user_id) {
global $user;
if ($user_id == $user->uid || user_access('user results')) {
$results = array();
$sql = "SELECT n.nid, n.title, u.name, qnrs.result_id, qnrs.time_start, qnrs.time_end\n FROM {node} n \n INNER JOIN {quiz_node_properties} qnp\n INNER JOIN {quiz_node_results} qnrs\n INNER JOIN {users} u\n WHERE n.type = 'quiz'\n AND n.nid = qnp.nid\n AND qnrs.nid = qnp.nid\n AND u.uid = qnrs.uid\n AND u.uid = %d\n ORDER BY qnrs.result_id ASC";
$dbresult = db_query($sql, $user_id);
// Create an array out of the results.
while ($line = db_fetch_array($dbresult)) {
$results[$line['result_id']] = $line;
}
return theme('quiz_get_user_results', $results);
}
else {
return 'You have no permission to view the results of this user.';
}
}
// THEME FUNCTIONS
/**
* Theme a message about the quiz's availability for quiz takers.
*
* @ingroup themeable
*/
function theme_quiz_availability($node) {
$status = _quiz_availability($node);
$output = '<div class="quiz_availability"><p>';
switch ($status) {
case 'future':
$output .= t('This quiz will not be available until %time.', array(
'%time' => format_date($node->quiz_open),
));
break;
case 'open':
$output .= t('This quiz closes %time.', array(
'%time' => format_date($node->quiz_close),
));
break;
case 'closed':
$output .= t('This quiz is no longer available.');
break;
}
$output .= '</p></div>' . "\n";
return $output;
}
/**
* Theme the node view for quizzes.
*
* @ingroup themeable
*/
function theme_quiz_view($node, $teaser = FALSE, $page = FALSE) {
$output = '';
// Output quiz options.
$output .= '<h3>' . t('@quiz Options', array(
'@quiz' => QUIZ_NAME,
)) . '</h3>';
$header = array(
t('# of Random Questions'),
t('Shuffle?'),
t('Feedback'),
t('Number of takes'),
);
$shuffle = $node->shuffle == 1 ? t('Yes') : t('No');
$feedback_options = _quiz_get_feedback_options();
$feedback = $feedback_options[$node->feedback_time];
$takes = $node->takes == 0 ? t('Unlimited') : check_plain($node->takes);
$rows = array();
$rows[] = array(
check_plain($node->number_of_random_questions),
$shuffle,
$feedback,
$takes,
);
$output .= theme('table', $header, $rows);
// Format Quiz Dates.
$output .= '<h3>' . t('@quiz start/end', array(
'@quiz' => QUIZ_NAME,
)) . '</h3>';
if (!$node->quiz_always) {
// If we are previewing, make sure the dates are timestamps and not form arrays.
if (is_array($node->quiz_open)) {
quiz_translate_form_date($node, 'quiz_open');
}
if (is_array($node->quiz_close)) {
quiz_translate_form_date($node, 'quiz_close');
}
// Format the availability info.
$output .= '<p>' . format_date($node->quiz_open) . ' — ' . format_date($node->quiz_close) . '</p>';
$output .= '<p><strong>' . t('Days @quiz live for: ', array(
'@quiz' => QUIZ_NAME,
)) . '</strong> ' . floor(($node->quiz_close - $node->quiz_open) / 60 / 60 / 24) . '</p>';
$remaining = floor(($node->quiz_close - time()) / 60 / 60 / 24);
$remaining = $remaining < 0 ? 'Expired' : $remaining;
$output .= '<p><strong>Days remaining:</strong> ' . $remaining . '</p>';
$elapsed = floor((time() - $node->quiz_open) / 60 / 60 / 24);
$elapsed = $elapsed < 0 ? -$elapsed . ' days to go' : $elapsed;
$output .= '<p><strong>Days since start:</strong> ' . $elapsed . '</p>';
}
else {
$output .= '<p>' . t('This Quiz is always available.') . '</p>' . "\n";
}
// Format taxonomy selection (if applicable).
if (function_exists(taxonomy_node_get_terms)) {
$output .= '<h3>' . t('Taxonomy selection') . '</h3>';
$terms = array();
foreach (taxonomy_node_get_terms($node) as $term) {
$terms[] = check_plain($term->name);
}
if (!empty($terms)) {
$terms = implode(', ', $terms);
$output .= "<p>{$terms}</p>";
}
else {
$output .= '<p>' . t('No selected terms found') . '</p>';
}
}
// Format pass / fail and summary options.
if ($node->pass_rate || $node->summary_default || $node->summary_pass) {
if ($node->pass_rate) {
$output .= '<h3>' . t('Pass / fail and summary options') . '</h3>' . "\n";
$output .= '<p><strong>' . t('Percentage needed to pass:') . '</strong> ' . check_plain($node->pass_rate) . '</p>' . "\n";
$output .= '<div><strong>' . t('Summary text if the user passed:') . '</strong> ';
$output .= $node->summary_pass ? check_markup($node->summary_pass) : t('No text defined.');
$output .= '</div>' . "\n";
}
$output .= '<div><strong>' . t('Default summary text:') . '</strong> ';
$output .= $node->summary_default ? check_markup($node->summary_default) : t('No text defined.');
$output .= '</div>' . "\n";
}
// Format result options if available.
if (count($node->resultoptions)) {
$scored_quiz = $node->pass_rate > 0;
$output .= '<h3>' . t('@quiz Results', array(
'@quiz' => QUIZ_NAME,
)) . '</h3>';
$header = array(
t('Name') => 'option_name',
t('Summary') => 'option_summary',
);
if ($scored_quiz) {
$header = array_merge($header, array(
t('Start') => 'option_start',
t('End') => 'option_end',
));
}
$values = array_values($header);
foreach ($node->resultoptions as $option) {
$row = array();
foreach ($values as $field) {
$row[] = $option[$field];
}
$option_rows[] = $row;
}
$output .= theme('table', array_keys($header), $option_rows);
}
// Format quiz questions.
if (is_numeric(arg(1))) {
$output .= '<h3>' . t('@quiz Questions', array(
'@quiz' => QUIZ_NAME,
)) . '</h3>';
$questions = _quiz_get_questions($node->vid);
$output .= theme('quiz_question_table', $questions, $node->nid);
}
return $output;
}
/**
* Theme the user results page.
*
* @param $results
* An array of quiz information.
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_get_user_results($results) {
$output = '';
$rows = array();
while (list($key, $result) = each($results)) {
$rows[] = array(
l('view', 'user/quiz/' . $result['result_id'] . '/userresults'),
check_plain($result['title']),
check_plain($result['name']),
$result['result_id'],
format_date($result['time_start'], 'small'),
$result['time_end'] > 0 ? format_date($result['time_end'], 'small') : t('In Progress'),
);
}
$header = array(
t('Action'),
t('@quiz Title', array(
'@quiz' => QUIZ_NAME,
)),
t('Username'),
t('Result<br />ID'),
t('Time Started'),
t('Finished?'),
);
if (!empty($rows)) {
$output .= theme('table', $header, $rows);
}
else {
$output .= t('No @quiz results found.', array(
'@quiz' => QUIZ_NAME,
));
}
return $output;
}
/**
* Theme the filtered question list.
*
* @ingroup themeable
*/
function theme_quiz_filtered_questions($form) {
$quiz_id = is_numeric(arg(1)) ? arg(1) : NULL;
$header = array(
t('Random'),
t('Always'),
t('Never'),
t('Question'),
t('Type'),
t('Edit'),
);
$rows = array();
while (list($nid, $values) = each($form['question_status'])) {
if (is_numeric($nid)) {
$rows[] = array(
drupal_render($form['question_status'][$nid][QUIZ_FEEDBACK_END]),
drupal_render($form['question_status'][$nid][QUIZ_FEEDBACK_QUESTION]),
drupal_render($form['question_status'][$nid][QUIZ_FEEDBACK_NEVER]),
drupal_render($form['question'][$nid]),
drupal_render($form['type'][$nid]),
l(t('Edit'), 'node/' . $nid . '/edit/' . $quiz_id),
);
}
}
if (!empty($rows)) {
$output .= theme('table', $header, $rows);
}
else {
$output .= t('No questions found.');
}
return $output;
}
/**
* Theme a table containing array of questions and options.
*
* @param $questions
* Array of question nodes.
* @return
* HTML for a table.
*
* @ingroup themeable
*/
function theme_quiz_question_table($questions, $quiz_id = NULL) {
$output = '';
$rows = array();
$status_descriptions = array(
t('Random'),
t('Always'),
t('Never'),
);
while (list($key, $question) = each($questions)) {
$rows[] = array(
$status_descriptions[$question->status],
$question->question,
$question->type,
l(t('Edit'), 'node/' . $question->nid . '/edit/' . $quiz_id),
);
}
$header = array(
t('Status'),
t('Question'),
t('Type'),
t('Edit'),
);
if (!empty($rows)) {
$output .= theme('table', $header, $rows);
}
else {
$output .= t('No questions found.');
}
return $output;
}
/**
* Pass the correct mark to the theme so that theme authors can use an image.
*
* @ingroup themeable
*/
function theme_quiz_score_correct() {
return theme('image', drupal_get_path('module', 'quiz') . '/images/correct.gif', t('correct'));
}
/**
* Pass the incorrect mark to the theme so that theme authors can use an image.
*
* @ingroup themeable
*/
function theme_quiz_score_incorrect() {
return theme('image', drupal_get_path('module', 'quiz') . '/images/incorrect.gif', t('incorrect'));
}
/**
* Theme a progress indicator for use during a quiz.
*
* @param $question_number
* The position of the current question in the sessions' array.
* @param $num_of_question
* The number of questions for this quiz as returned by quiz_get_number_of_questions().
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_progress($question_number, $num_of_question) {
// Determine the percentage finished (not used, but left here for other implementations).
//$progress = ($question_number*100)/$num_of_question;
// Get the current question # by adding one.
$current_question = $question_number + 1;
$output = '';
$output .= '<div id="quiz_progress">';
$output .= t('Question %x of %y', array(
'%x' => $current_question,
'%y' => $num_of_question,
));
$output .= '</div><br />' . "\n";
return $output;
}
/**
* Theme a question page.
*
* @param $quiz
* The quiz node object.
* @param $question_node
* The question node.
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_take_question($quiz, $question_node) {
//Calculation for quiz progress bar.
$number_of_questions = quiz_get_number_of_questions($quiz->vid, $quiz->nid);
$question_number = $number_of_questions - count($_SESSION['quiz_' . $quiz->nid]['quiz_questions']);
$question_node->question_number = $question_number;
// Set the title here in case themers want to do something different.
drupal_set_title(check_plain($quiz->title));
// Return the elements of the page.
$output = '';
$output .= theme('quiz_progress', $question_number, $number_of_questions);
$output .= module_invoke($question_node->type, 'render_question', $question_node);
return $output;
}
/**
* Theme the summary page after the quiz has been completed.
*
* @param $quiz
* The quiz node object.
* @param $questions
* The questions array as defined by _quiz_get_answers.
* @param $score
* Array of score information as returned by quiz_calculate_score().
* @param $summary
* Filtered text of the summary.
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_take_summary($quiz, $questions, $score, $summary) {
// Set the title here so themers can adjust.
drupal_set_title(check_plain($quiz->title));
// Display overall result.
$output = '';
if ($score['percentage_score']) {
$output .= '<div id="quiz_score_possible">' . t('You got %num_correct of %question_count correct.', array(
'%num_correct' => $score['num_correct'],
'%question_count' => $score['question_count'],
)) . '</div>' . "\n";
$output .= '<div id="quiz_score_percent">' . t('Your score: %score%', array(
'%score' => $score['percentage_score'],
)) . '</div><br />' . "\n";
}
$output .= '<div id="quiz_summary">' . check_markup($summary, $quiz->format) . '</div><br />' . "\n";
// Get the feedback for all questions.
$output .= theme('quiz_feedback', $questions, $quiz->pass_rate > 0, TRUE);
return $output;
}
/**
* Theme the summary page for user results.
*
* @param $quiz
* The quiz node object.
* @param $questions
* The questions array as defined by _quiz_get_answers.
* @param $score
* Array of score information as returned by quiz_calculate_score().
* @param $summary
* Filtered text of the summary.
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_user_summary($quiz, $questions, $score, $summary) {
// Set the title here so themers can adjust.
drupal_set_title(check_plain($quiz->title));
// Display overall result.
$output = '';
$output .= '<div id="quiz_score_possible">' . t('You got %num_correct of %question_count correct.', array(
'%num_correct' => $score['num_correct'],
'%question_count' => $score['question_count'],
)) . '</div>' . "\n";
$output .= '<div id="quiz_score_percent">' . t('Your score was: @score%', array(
'@score' => $score['percentage_score'],
)) . '</div><br />' . "\n";
$output .= '<div id="quiz_summary">' . check_markup($summary, $quiz->format) . '</div><br />' . "\n";
// Get the feedback for all questions.
$output .= theme('quiz_feedback', $questions, FALSE, TRUE);
return $output;
}
/**
* Theme the question feedback.
*
* @param $questions
* Array of quiz objects as returned by _quiz_get_answers.
* @param showpoints
* Binary flag for whether to show the actual answers or not.
* @param $showfeedback
* Binary flag for whether to show question feedback.
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_feedback($questions, $showpoints = TRUE, $showfeedback = FALSE) {
$header = array(
t('Question Result(s)'),
'',
);
// Go through each of the questions.
foreach ($questions as $question) {
$cols = array();
// Ask each question to render a themed report of how the user did.
$cols[] = array(
'data' => theme($question->type . '_report', $question, $showpoints, $showfeedback),
'class' => 'quiz_summary_qrow',
);
// Get the score result for each question only if it's a scored quiz.
if ($showpoints) {
$theme = $question->correct ? 'quiz_score_correct' : 'quiz_score_incorrect';
$cols[] = array(
'data' => theme($theme),
'class' => 'quiz_summary_qcell',
);
}
// Pack all of this into a table row.
$rows[] = array(
'data' => $cols,
'class' => 'quiz_summary_qrow',
);
}
return theme('table', $header, $rows);
}
/**
* Theme feedback for one question.
*
* @param $quiz
* Quiz node (may not be needed).
* @param $question_node
* The question node giving feedback for.
* @param $answer
* User's response to previous question.
* @return
* Themed html.
*
* @ingroup themeable
*/
function theme_quiz_question_feedback($quiz, $report) {
$output = '<div class="quiz-summary-question">';
$output .= theme($report->type . '_feedback', $quiz, $report);
$output .= '</div><br class="clear" />';
return $output;
}
/**
* Allow the option to theme the questions form.
*
* @ingroup themeable
*/
function theme_quiz_questions($form) {
$output = '';
$output .= drupal_render($form);
return $output;
}
/**
* Theme the "no feedback" option.
*
* @return
* Themed html feedback.
*
* @ingroup themeable
*/
function theme_quiz_no_feedback() {
return t('Thanks for taking the quiz!');
}
Functions
Name | Description |
---|---|
quiz_get_user_results | Displays all the quizzes the user has taken part in. |
quiz_user_results | |
theme_quiz_availability | Theme a message about the quiz's availability for quiz takers. |
theme_quiz_feedback | Theme the question feedback. |
theme_quiz_filtered_questions | Theme the filtered question list. |
theme_quiz_get_user_results | Theme the user results page. |
theme_quiz_no_feedback | Theme the "no feedback" option. |
theme_quiz_progress | Theme a progress indicator for use during a quiz. |
theme_quiz_questions | Allow the option to theme the questions form. |
theme_quiz_question_feedback | Theme feedback for one question. |
theme_quiz_question_table | Theme a table containing array of questions and options. |
theme_quiz_score_correct | Pass the correct mark to the theme so that theme authors can use an image. |
theme_quiz_score_incorrect | Pass the incorrect mark to the theme so that theme authors can use an image. |
theme_quiz_take_question | Theme a question page. |
theme_quiz_take_summary | Theme the summary page after the quiz has been completed. |
theme_quiz_user_summary | Theme the summary page for user results. |
theme_quiz_view | Theme the node view for quizzes. |