og_quiz.module in OG Quiz 7
Module hooks and custom logic.
File
og_quiz.moduleView source
<?php
/**
* @file
* Module hooks and custom logic.
*/
/**
* Implements hook_menu_alter().
*/
function og_quiz_menu_alter(&$items) {
$items['node/%node/take']['access callback'] = 'og_quiz_take_access';
$items['node/%node/results']['access callback'] = 'og_quiz_access_results';
$items['node/%node/results/%quiz_rid']['access callback'] = 'og_quiz_access_results';
$items['user/%/myresults']['page callback'] = 'og_quiz_get_user_results';
$items['user/%/myresults']['access callback'] = 'og_quiz_user_results_access';
$items['user/quiz/%/userresults']['access callback'] = 'og_quiz_access_my_result';
}
/**
* Implements hook_node_prepare().
*/
function og_quiz_node_prepare($node) {
$question_types = array_keys(_quiz_question_get_implementations());
$type = is_string($node) ? $node : $node->type;
if (in_array($type, $question_types)) {
if (isset($_GET['quiz_nid'])) {
$quiz = node_load($_GET['quiz_nid'], isset($_GET['quiz_vid']) ? $_GET['quiz_vid'] : NULL);
if (!empty($quiz->og_group_ref)) {
$node->og_group_ref = $quiz->og_group_ref;
}
}
}
}
/**
* Implements hook_node_view().
*/
function og_quiz_node_view($node, $view_mode, $langcode) {
if ($node->type == 'quiz') {
if (empty($node->content['take'])) {
$available = quiz_availability($node);
if ($available) {
if (og_quiz_ogs_access($node, 'access quiz')) {
if ($view_mode == 'full') {
$quiz_form = drupal_get_form('quiz_start_quiz_button_form', $node);
$node->content['take'] = array(
'#markup' => drupal_render($quiz_form),
'#weight' => 2,
);
}
else {
$node->content['take'] = array(
'#markup' => l(t('Start quiz'), 'node/' . $node->nid . '/take'),
'#weight' => 2,
);
}
}
}
}
}
}
/**
* Implements hook_theme_registry_alter().
*/
function og_quiz_theme_registry_alter(&$registry) {
unset($registry['quiz_admin_summary']['file']);
$registry['quiz_admin_summary']['function'] = 'theme_og_quiz_quiz_admin_summary';
}
/**
* Implements hook_registry_files_alter().
*/
function og_quiz_registry_files_alter(&$files, $modules) {
$to_delete = array();
if (module_exists('quiz_question')) {
// Replace the QuizQuestion class with our own.
$path = drupal_get_path('module', 'quiz_question');
unset($files["{$path}/quiz_question.core.inc"]);
$to_delete[] = drupal_get_path('module', 'og_quiz') . '/includes/og_quiz_question.php';
}
if (module_exists('long_answer')) {
// Replace the LongAnswerResponse class with our own.
$path = drupal_get_path('module', 'long_answer');
unset($files["{$path}/long_answer.classes.inc"]);
$to_delete[] = drupal_get_path('module', 'og_quiz') . '/includes/og_long_answer.php';
}
if (!empty($to_delete)) {
// Force delete of the cached entry, so the registry can be rebuilt corectly.
db_delete('registry_file')
->condition('filename', $to_delete, 'IN')
->execute();
}
}
/**
* Implements hook_og_permissions().
*/
function og_quiz_og_permission() {
return array(
'access quiz' => array(
'title' => t('Take quiz'),
'description' => t('Can access (take) all quizzes.'),
),
'view any quiz results' => array(
'title' => t('View any quiz results'),
'description' => t('Can view results for all quizzes and users.'),
),
'view own quiz results' => array(
'title' => t('View own quiz results'),
'description' => t('Quiz takers can view their own results, also when quiz is not passed.'),
),
'view results for own quiz' => array(
'title' => t('View results for own quiz'),
'description' => t('Quiz makers can view results for their own quizzes.'),
),
'delete any quiz results' => array(
'title' => t('Delete any quiz results'),
),
'delete results for own quiz' => array(
'title' => t('Delete results for own quiz'),
),
'score any quiz' => array(
'title' => t('Score any quiz'),
),
'score own quiz' => array(
'title' => t('Score own quiz'),
),
'score taken quiz answer' => array(
'title' => t('score taken quiz answer'),
'description' => t('Allows attendee to score questions needing manual evaluation.'),
),
);
}
/**
* Implements hook_form_BASE_ID_alter() for node_form().
*/
function og_quiz_form_node_form_alter(&$form, $form_state, $form_id) {
$question_types = array_keys(_quiz_question_get_implementations());
$type = str_replace('_node_form', '', $form_id);
if (in_array($type, $question_types)) {
// Newer versions of OG introduce a bug with the og_group_ref. Unset the prefilled admin
// field.
if (!isset($form['#og_quiz_processed']) && !empty($form['og_group_ref'][LANGUAGE_NONE][0]['admin'])) {
foreach ($form['og_group_ref'][LANGUAGE_NONE][0]['admin'] as $key => $value) {
if (is_numeric($key)) {
$form['og_group_ref'][LANGUAGE_NONE][0]['admin'][$key]['target_id']['#default_value'] = '';
}
}
$form['#og_quiz_processed'] = TRUE;
}
}
}
/**
* Implements hook_form_quiz_results_manage_results_form_alter().
*/
function og_quiz_form_quiz_results_manage_results_form_alter(&$form, $form_state) {
global $user;
$quiz = $form_state['build_info']['args'][0];
if (og_quiz_ogs_access($quiz, 'delete any quiz results') || og_quiz_ogs_access($quiz, 'delete results for own quiz') && $user->uid && $quiz->uid) {
$display = isset($_GET['del']) || isset($form_state['storage']['del']) ? 'none' : 'block';
$form['update'] = array(
'#type' => 'fieldset',
'#title' => t('Options'),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#attributes' => array(
'class' => array(
'container-inline',
),
'id' => 'quiz-results-update',
'style' => "display:{$display};",
),
'#weight' => -10,
);
$form['update']['bulk_action'] = array(
'#type' => 'select',
'#options' => array(
'def' => '',
'del' => t('delete'),
),
);
$form['update']['update'] = array(
'#type' => 'submit',
'#value' => t('Update'),
);
// We show the delete confirmation fieldset if we are to delete results
$display = isset($_GET['del']) || isset($form_state['storage']['del']) ? 'block' : 'none';
$form['confirm_delete'] = array(
'#type' => 'fieldset',
'#title' => t('Confirm deletion'),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#attributes' => array(
'style' => "display:{$display};",
'id' => 'quiz-results-confirm-delete',
),
'#weight' => -10,
);
$form['confirm_delete']['help'] = array(
'#type' => 'item',
'#value' => t('Are you sure you want to delete all of these results?'),
'#description' => t('This action cannot be undone'),
);
$form['confirm_delete']['confirm_delete'] = array(
'#type' => 'submit',
'#value' => t('Delete all marked results'),
);
$form['confirm_delete']['cancel'] = array(
'#markup' => l(t('cancel'), $_GET['q'], array(
'attributes' => array(
'id' => 'quiz-results-cancel-delete',
),
)),
);
}
}
/**
* Custom access callback for accessing quiz results.
*
* @param stdClass $node
* @param int $rid
*
* @return bool
*/
function og_quiz_access_results($node, $rid = NULL) {
if ($node->type != 'quiz') {
if ($node->type == 'poll' && module_exists("poll")) {
return _poll_menu_access($node, 'access content', TRUE);
}
return FALSE;
}
if (!($access = og_quiz_ogs_access($node, 'view any quiz results'))) {
global $user;
if ($access = og_quiz_ogs_access($node, 'view results for own quiz')) {
$access = $access && $node->uid == $user->uid;
}
if (!$access) {
if ($access = og_quiz_ogs_access($node, 'score taken quiz answer')) {
if (isset($rid)) {
$res = db_query('SELECT qnr.nid, qnr.uid FROM {quiz_node_results} qnr WHERE result_id = :result_id', array(
':result_id' => $rid,
))
->fetch();
if ($res && $res->nid != $node->nid) {
return FALSE;
}
}
$access = $access && isset($rid) && $res && $res->uid == $user->uid;
}
}
}
return isset($access) ? $access : quiz_access_results($node, $rid);
}
/**
* Custom access callback for taking quiz.
*
* @param stdClass $node
*
* @return bool
*/
function og_quiz_take_access($node) {
if ($node->type != 'quiz' || !quiz_availability($node)) {
return FALSE;
}
$access = og_quiz_ogs_access($node, 'access quiz');
return isset($access) ? $access : quiz_take_access($node);
}
/**
* Custom access callback for viewing user results tab
*
* @param int $uid
*
* @return bool
*/
function og_quiz_user_results_access($uid) {
global $user;
if (!($access = og_quiz_user_access($user, 'view any quiz results'))) {
if ($access = og_quiz_user_access($user, 'view own quiz results')) {
$access = $access && $uid == $user->uid;
}
}
return isset($access) ? $access : _quiz_user_results_access($uid);
}
/**
* Custom access callback for viewing own results.
*
* @param int $rid
*
* @return bool
*/
function og_quiz_access_my_result($rid) {
global $user;
$access = FALSE;
$result = db_query('SELECT uid,time_end FROM {quiz_node_results} WHERE result_id = :result_id', array(
':result_id' => $rid,
))
->fetchAssoc();
if (!empty($result)) {
if (user_access('view any quiz results')) {
return TRUE;
}
else {
$access = $result['time_end'] > 0;
if ($access) {
if (!($access = user_access('view own quiz results'))) {
return og_quiz_user_access($user, 'view own quiz results');
}
}
}
}
return $access;
}
/**
* Helper function to check multiple permissions on all node groups.
* Returns null if no groups are available.
*
* @param stdClass $node
* @param string|array $permissions
* @param stdClass $account = NULL
*
* @return bool|null
*/
function og_quiz_ogs_access($node, $permissions, $account = NULL) {
$groups = og_get_entity_groups('node', $node);
if (!empty($groups)) {
if (is_string($permissions)) {
$permissions = array(
$permissions,
);
}
if (!isset($account)) {
global $user;
$account = clone $user;
}
foreach ($groups as $entity_type => $entity_groups) {
foreach ($entity_groups as $etid => $gid) {
foreach ($permissions as $permission) {
if (og_user_access($entity_type, $gid, $permission, $account)) {
return TRUE;
}
}
}
}
return FALSE;
}
return NULL;
}
/**
* Helper function to check multiple permissions on all user groups.
* Returns null if no groups are available.
*
* @param stdClass $account
* @param string|array $permissions
*
* @return bool|null
*/
function og_quiz_user_access($account, $permissions) {
$groups = og_get_entity_groups('user', $account);
if (!empty($groups)) {
if (is_string($permissions)) {
$permissions = array(
$permissions,
);
}
foreach ($groups as $entity_type => $entity_groups) {
foreach ($entity_groups as $etid => $gid) {
foreach ($permissions as $permission) {
if (og_user_access($entity_type, $gid, $permission, $account)) {
return TRUE;
}
}
}
}
return FALSE;
}
return NULL;
}
/**
* Theme the result summary. This is almost a verbatim copy of theme_quiz_admin_summary(). Add OG access
* control.
*/
function theme_og_quiz_quiz_admin_summary($variables) {
global $user;
$quiz = $variables['quiz'];
$questions = $variables['questions'];
$score = $variables['score'];
$summary = $variables['summary'];
$rid = $variables['rid'];
$account = $variables['account'];
// To adjust the title uncomment and edit the line below:
// drupal_set_title(check_plain($quiz->title));
if (!$score['is_evaluated']) {
drupal_set_message(t('This lesson has not been scored yet.'), 'warning');
}
// Display overall result.
$output = '';
$params = array(
'%num_correct' => $score['numeric_score'],
'%question_count' => $score['possible_score'],
'!username' => theme('username', array(
'account' => $account,
)),
);
$output .= '<div id="quiz_score_possible">' . t('!username got %num_correct of %question_count possible points.', $params) . '</div>' . "\n";
$output .= '<div id="quiz_score_percent">' . t('Total score: @score %', array(
'@score' => $score['percentage_score'],
)) . '</div>' . "\n";
$quiz_format = isset($quiz->body[LANGUAGE_NONE][0]['format']) ? $quiz->body[LANGUAGE_NONE][0]['format'] : NULL;
if (isset($summary['passfail'])) {
$output .= '<div id="quiz_summary">' . check_markup($summary['passfail'], $quiz_format) . '</div>' . "\n";
}
if (isset($summary['result'])) {
$output .= '<div id="quiz_summary">' . check_markup($summary['result'], $quiz_format) . '</div>' . "\n";
}
// Get the feedback for all questions.
require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'quiz') . '/quiz.pages.inc';
if (!($access = og_quiz_ogs_access($quiz, 'score any quiz'))) {
if ($access = og_quiz_ogs_access($quiz, 'score own quiz')) {
$access = $access && $quiz->uid && $user->uid;
}
}
$access = isset($access) ? $access : user_access('score any quiz') || user_access('score own quiz') && $quiz->uid && $user->uid;
$report_form = drupal_get_form('quiz_report_form', $questions, TRUE, TRUE, $access);
$output .= drupal_render($report_form);
return $output;
}
/**
* Page callback for viewing user results.
* Filter by courses the viewer is actually a member of.
* @see quiz_get_user_results().
*
* @param int $uid
*
* @return string
*/
function og_quiz_get_user_results($uid) {
module_load_include('inc', 'quiz', 'quiz.pages');
global $user;
// In some edge-cases, we get the user object instead of the uid.
if (is_object($uid) && isset($uid->uid)) {
$uid = $uid->uid;
}
// This is a verbatim copy of quiz_get_user_results().
$results = array();
$dbresult = db_query('SELECT DISTINCT(n.nid), n.title, qnp.pass_rate, qnrs.result_id, qnrs.time_start, qnrs.time_end, qnrs.score, qnrs.is_evaluated
FROM {node} n
INNER JOIN {quiz_node_properties} qnp ON n.nid = qnp.nid
INNER JOIN {quiz_node_results} qnrs ON qnrs.vid = qnp.vid
INNER JOIN {users} u ON u.uid = qnrs.uid
WHERE n.type = :type
AND u.uid = :uid
ORDER BY qnrs.result_id DESC', array(
':type' => 'quiz',
':uid' => $uid,
));
// Create an array out of the results.
foreach ($dbresult as $result) {
$result = (array) $result;
$access = TRUE;
// Start filtering based on access levels.
if (!user_access('view any quiz results')) {
$quiz = node_load($result['nid']);
if (!(user_access('view results for own quiz') && $user->uid == $quiz->uid)) {
// Check group permissions.
if (!og_quiz_ogs_access($quiz, 'view any quiz results')) {
if (!(og_quiz_ogs_access($quiz, 'view results for own quiz') && $user->uid == $quiz->uid)) {
// Is it the user herself ?
if (!(user_access('view own quiz results') && $user->uid == $uid)) {
if (!(og_quiz_ogs_access($quiz, 'view own quiz results') && $user->uid == $uid)) {
$access = FALSE;
}
}
}
}
}
}
// Filter by groups the user can see
if ($access) {
$results[$result['result_id']] = $result;
}
}
return theme('quiz_get_user_results', array(
'results' => $results,
));
}
Functions
Name | Description |
---|---|
og_quiz_access_my_result | Custom access callback for viewing own results. |
og_quiz_access_results | Custom access callback for accessing quiz results. |
og_quiz_form_node_form_alter | Implements hook_form_BASE_ID_alter() for node_form(). |
og_quiz_form_quiz_results_manage_results_form_alter | Implements hook_form_quiz_results_manage_results_form_alter(). |
og_quiz_get_user_results | Page callback for viewing user results. Filter by courses the viewer is actually a member of. |
og_quiz_menu_alter | Implements hook_menu_alter(). |
og_quiz_node_prepare | Implements hook_node_prepare(). |
og_quiz_node_view | Implements hook_node_view(). |
og_quiz_ogs_access | Helper function to check multiple permissions on all node groups. Returns null if no groups are available. |
og_quiz_og_permission | Implements hook_og_permissions(). |
og_quiz_registry_files_alter | Implements hook_registry_files_alter(). |
og_quiz_take_access | Custom access callback for taking quiz. |
og_quiz_theme_registry_alter | Implements hook_theme_registry_alter(). |
og_quiz_user_access | Helper function to check multiple permissions on all user groups. Returns null if no groups are available. |
og_quiz_user_results_access | Custom access callback for viewing user results tab |
theme_og_quiz_quiz_admin_summary | Theme the result summary. This is almost a verbatim copy of theme_quiz_admin_summary(). Add OG access control. |