You are here

qcollection.module in Quiz 6.6

The main file for qcollection.

A question item collection organizes quiz questions to make them easier to find and to collect together for one's personal use.

An item collection can be turned into a quiz for taking by a student.

File

includes/qcollection/qcollection.module
View source
<?php

/**
 * The main file for qcollection.
 *
 * A question item collection organizes quiz questions to make them easier to find
 * and to collect together for one's personal use.
 *
 * An item collection can be turned into a quiz for taking by a student.
 *
 * @file
 */
define('QCOLLECTION_NAME', 'Question item collection');

/**
 * Implementation of hook_help().
 */
function qcollection_help($path, $args) {
  if ($path == 'admin/help#qcollection') {
    return t('This module provides a question item collection type for Quiz.');
  }
}

/**
 * Implementation of hook_perm().
 */
function qcollection_perm() {
  return array(
    // Managing qcollections:
    'access qcollection',
    'create qcollection',
    'edit own qcollection',
    'edit any qcollection',
    'delete any qcollection',
    'delete own qcollection',
  );
}

/**
 * Implementation of hook_access().
 */
function qcollection_access($op, $node, $account) {

  // Admin can do all of this.
  if (user_access('administer quiz', $account)) {
    return TRUE;
  }
  if (!user_access('access qcollection')) {

    // If you can't access, you get NOTHING!
    // Otherwise, we allow further permission checking.
    return FALSE;
  }
  switch ($op) {
    case 'create':
      return user_access('create qcollection', $account);
    case 'update':
      return user_access('edit any qcollection', $account) || user_access('edit own qcollection', $account) && $account->uid == $node->uid;
    case 'delete':
      return user_access('delete any qcollection', $account) || user_access('delete own qcollection', $account) && $account->uid == $node->uid;
  }
}

/**
 * Implementation of hook_node_info().
 */
function qcollection_node_info() {
  return array(
    'qcollection' => array(
      'name' => t(QCOLLECTION_NAME),
      'module' => 'qcollection',
      'description' => t('A content type for the quiz module: gathers question items into a collection, separate from quiz-taking.'),
      'has_title' => TRUE,
      'has_body' => TRUE,
      'body_label' => t('Notes'),
    ),
  );
}

/**
 * Implementation of qcollection_menu().
 */
function qcollection_menu() {

  // Menu item for managing items in a collection
  $items['node/%qcollection_type_access/items'] = array(
    'title' => t('Manage items'),
    'page callback' => 'qcollection_items',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'node_access',
    'access arguments' => array(
      'update',
      1,
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'qcollection.inc',
  );

  // Menu item to export item list into a new quiz
  $items['node/%qcollection_type_access/export-quiz'] = array(
    'title' => t('Export as quiz'),
    'page callback' => 'qcollection_export_quiz',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'user_access',
    'access arguments' => array(
      'create quiz',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'qcollection.inc',
  );

  // Menu item to download item collection in a portable format
  $items['node/%qcollection_type_access/download'] = array(
    'title' => t('Download'),
    'page callback' => 'qcollection_download',
    'page arguments' => array(
      1,
    ),
    // FIXME: This needs to check to see if the user owns the qcollection.
    'access callback' => 'node_access',
    'access arguments' => array(
      'update',
      1,
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'qcollection.inc',
  );
  return $items;
}

/**
 * Implementation of hook_theme().
 */
function qcollection_theme() {
  return array(
    'qcollection_question_table' => array(
      'arguments' => array(
        'questions' => NULL,
        'quiz_id' => NULL,
      ),
      'file' => 'qcollection.pages.inc',
    ),
  );
}

/**
 * Load a qcollection node and validate it.
 *
 * @param $arg
 *  The Node ID
 * @return
 *  A qcollection node object or FALSE if a load failed.
 */
function qcollection_type_access_load($arg) {

  // Simple verification/load of the node.
  //  ddebug_backtrace();
  return ($node = node_load($arg)) && $node->type == 'qcollection' ? $node : FALSE;
}
function _qcollection_get_info($node) {
  $quiz_vid = db_result(db_query("SELECT vid FROM {node} WHERE nid = %d", $quiz_nid));

  // Get count of child questions (ignoring question_status)
  $sql = 'SELECT COUNT(child_nid)
    FROM {quiz_node_relationship}
    WHERE parent_vid = %d
      AND parent_nid = %d';
  $questions_count = db_result(db_query($sql, $node->vid, $node->nid));
  return compact('questions_count');
}

/**
 * Implemention of hook_view().
 *
 */
function qcollection_view($node, $teaser = FALSE, $page = FALSE, $links = TRUE) {
  $node = node_prepare($node, $teaser);
  $collection_nid = $node->nid;
  $info = _qcollection_get_info($node);
  $node->content['info'] = array(
    // TODO theme the info block
    '#value' => "<em>{$info['questions_count']} questions</em><br/>",
    '#weight' => 0,
  );
  if (!$teaser) {
    $questions = _quiz_get_questions($node->nid, $node->vid);
    $output = theme('qcollection_question_table', $questions, $collection_nid);
    $node->content['questions'] = array(
      '#value' => $output,
      '#weight' => 1,
    );
  }
  if (user_access('create quiz')) {
    $node->content['export-quiz'] = array(
      '#value' => l(t('Export as quiz'), 'node/' . $collection_nid . '/export-quiz'),
      '#weight' => 2,
    );
  }
  return $node;
}

/**
 * Implementation of hook_form().
 *
 */
function qcollection_form(&$node) {
  $type = node_get_types('type', $node);
  $form = array();
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => check_plain($type->title_label),
    '#default_value' => $node->title,
    '#description' => t('The name of the @item_collection.', array(
      '@item_collection' => QCOLLECTION_NAME,
    )),
    '#required' => TRUE,
  );
  $form['body_field']['body'] = array(
    '#type' => 'textarea',
    '#title' => check_plain($type->body_label),
    '#default_value' => $node->body,
    '#description' => t('Notes on the contents and origin of the @qcollection entails', array(
      '@qcollection' => QCOLLECTION_NAME,
    )),
    '#required' => FALSE,
  );
  $form['body_field']['format'] = filter_form($node->format);
  return $form;
}

/**
 * Implementation of hook_form_alter().
 *
 * Override settings in some existing forms. For example, we remove the
 * preview button on a qcollection.
 */
function qcollection_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'qcollection_node_form') {

    // Remove preview buttons:
    unset($form['buttons']['preview']);
    unset($form['buttons']['preview_changes']);

    // TODO make preview work
  }
}

/**
 * Implementation of hook_update().
 */
function qcollection_update($node) {

  // QCollection node vid (revision) was updated.
  if ($node->revision) {

    // Create new qcollection-question relation entries in the quiz_node_relationship table.
    quiz_update_quiz_question_relationship($node->old_vid, $node->vid, $node->nid);
  }
}

/**
 * Implementation of hook_delete().
 */
function qcollection_delete($node) {
  db_query('DELETE FROM {quiz_node_relationship} WHERE parent_nid = %d', $node->nid);
}

/**
 * Implementation of hook_action_info()
 *
 * @return array of action info
 */
function qcollection_action_info() {
  return array(
    'qcollection_add_question_action' => array(
      'type' => 'node',
      // FIXME restrict to quiz question nodes
      'description' => t('Add to an item collection'),
      'configurable' => TRUE,
      'hooks' => array(
        'any' => TRUE,
      ),
    ),
  );
}

/**
* Return a form for selecting collections and quizzes to which a node should be copied
*/
function qcollection_add_question_action_form($context) {
  global $user;
  $form = array();

  // user's collections
  $sql = "SELECT nid, title\n FROM {node}\n WHERE (type in ('qcollection')) AND (uid = %d)";
  $result = db_query($sql, $user->uid);
  while ($row = db_fetch_array($result)) {
    $options[$row['nid']] = $row['title'];
  }

  // checkboxes for the qcollections the user has permission to add to
  $form['my_collections'] = array(
    '#type' => 'checkboxes',
    '#title' => t('My Collections'),
    '#options' => $options,
    '#description' => t('Collections to which you can add question items.'),
  );
  return $form;
}
function qcollection_add_question_action_validate($form, $form_state) {

  // validation code here ...
  // FIXME validate that the input nodes are all questions
}
function qcollection_add_question_action_submit($form, $form_state) {
  return array(
    'targets' => $form_state['values']['my_collections'],
  );
}

/**
 * Callback function to copy a question node to one or more collections
 */
function qcollection_add_question_action(&$node, $context) {
  _qcollection_add_question_to_collection($node, $context['targets']);
}

/**
 * Add a question node to a qcollection
 */
function _qcollection_add_question_to_collection($question, $collections) {
  $weight = 0;

  // Now we add the question node to each collection
  // (Note that we are using a subselect to get the most recent vid of the qcollection.)
  $sql = "INSERT INTO {quiz_node_relationship} (parent_nid, parent_vid, child_nid, child_vid, question_status, weight)\n      VALUES (%d, (SELECT vid FROM {node} WHERE nid = %d), %d, %d, %d, %d)";
  foreach (array_filter($collections) as $collection_nid) {
    db_query($sql, $collection_nid, $collection_nid, $question->nid, $question->vid, QUESTION_ALWAYS, $weight);
  }
}

Functions

Namesort descending Description
qcollection_access Implementation of hook_access().
qcollection_action_info Implementation of hook_action_info()
qcollection_add_question_action Callback function to copy a question node to one or more collections
qcollection_add_question_action_form Return a form for selecting collections and quizzes to which a node should be copied
qcollection_add_question_action_submit
qcollection_add_question_action_validate
qcollection_delete Implementation of hook_delete().
qcollection_form Implementation of hook_form().
qcollection_form_alter Implementation of hook_form_alter().
qcollection_help Implementation of hook_help().
qcollection_menu Implementation of qcollection_menu().
qcollection_node_info Implementation of hook_node_info().
qcollection_perm Implementation of hook_perm().
qcollection_theme Implementation of hook_theme().
qcollection_type_access_load Load a qcollection node and validate it.
qcollection_update Implementation of hook_update().
qcollection_view Implemention of hook_view().
_qcollection_add_question_to_collection Add a question node to a qcollection
_qcollection_get_info

Constants

Namesort descending Description
QCOLLECTION_NAME The main file for qcollection.