scale.module in Quiz 7
The main file for scale.
Sponsored by: Norwegian Centre for Telemedicine Code: falcon
Scale question type for the Quiz module.
Allows the creation of scale questions (ex: likert scale)
File
question_types/scale/scale.moduleView source
<?php
/**
* The main file for scale.
*
* Sponsored by: Norwegian Centre for Telemedicine
* Code: falcon
*
* @file
* Scale question type for the Quiz module.
*
* Allows the creation of scale questions (ex: likert scale)
*/
/**
* Implements hook_help().
*/
function scale_help($path, $args) {
if ($path == 'admin/help#scale') {
return t('This module provides a scale question type for Quiz. It may be used to construct surveys.');
}
}
/**
* Implements hook_menu().
*/
function scale_menu() {
$items['scale/collection/manage'] = array(
'title' => 'Manage your preset collections',
'access callback' => 'user_access',
'access arguments' => array(
'create quiz',
),
'type' => MENU_SUGGESTED_ITEM,
'page callback' => 'drupal_get_form',
'page arguments' => array(
'scale_manage_collection_form',
),
);
return $items;
}
/**
* Implements hook_theme().
*/
function scale_theme($existing, $type, $theme, $path) {
$module_path = drupal_get_path('module', 'scale');
return array(
'scale_creation_form' => array(
'render element' => 'form',
'path' => $module_path . '/theme',
'file' => 'scale.theme.inc',
),
'scale_response_form' => array(
'render element' => 'form',
'path' => $module_path . '/theme',
'file' => 'scale.theme.inc',
),
'scale_answer_node_view' => array(
'variables' => array(
'alternatives' => NULL,
),
'path' => $module_path . '/theme',
'file' => 'scale.theme.inc',
),
'scale_answering_form' => array(
'render element' => 'form',
'path' => $module_path . '/theme',
'template' => 'scale-answering-form',
),
);
}
/**
* Implements hook_permission().
*/
function scale_permission() {
return array(
'Edit global presets' => array(
'title' => t('Administer presets'),
),
);
}
/**
* Implements hook_quiz_question_info().
*/
function scale_quiz_question_info() {
return array(
'scale' => array(
'name' => t('Scale question'),
'description' => t('Quiz questions that allow a user to choose from a scale.'),
'question provider' => 'ScaleQuestion',
'response provider' => 'ScaleResponse',
'module' => 'quiz_question',
),
);
}
/**
* Implements hook_config().
*/
function scale_config() {
$form['manage'] = array(
'#markup' => l(t('Manage presets'), 'scale/collection/manage'),
);
$form['scale_max_num_of_alts'] = array(
'#type' => 'textfield',
'#title' => t('Maximum number of alternatives allowed'),
'#default_value' => variable_get('scale_max_num_of_alts', 10),
);
$form['#validate'] = 'scale_config_validate';
return $form;
}
/**
* Validate the scale config form values
*/
function scale_config_validate($form, $form_state) {
if (!_quiz_is_int($form_state['values']['scale_max_num_of_alts'], 2, 50)) {
form_set_error('scale_max_num_of_alts', t('The number of alternatives must be between 2 and 50'));
}
}
/**
* Implements hook_get_answer().
*/
function scale_get_answer($question_nid, $question_vid, $result_id) {
$results = db_query('SELECT answer_id, question_vid, question_nid, result_id
FROM {quiz_scale_user_answers}
WHERE question_nid = :qnid AND question_vid = :qvid AND result_id = :rid', array(
':qnid' => $question_nid,
':qvid' => $question_vid,
':rid' => $result_id,
))
->fetchAssoc();
return $results ? $results : FALSE;
}
/**
* Implements hook_user_cancel().
*/
function scale_user_cancel($edit, $account, $method) {
$results = db_query('SELECT id FROM {quiz_scale_answer_collection} ac
JOIN {quiz_scale_user} u ON(ac.id = u.answer_collection_id)
WHERE uid = :uid
AND ac.for_all = :for_all
AND ac.id NOT IN
(SELECT answer_collection_id
FROM {quiz_scale_node_properties})
AND ac.id NOT IN
(SELECT answer_collection_id
FROM {quiz_scale_user}
WHERE NOT uid = :uid)', array(
':uid' => $account->uid,
':for_all' => 0,
));
foreach ($results as $result) {
db_delete('quiz_scale_answer')
->condition('answer_collection_id', $result->id)
->execute();
db_delete('quiz_scale_answer_collection')
->condition('id', $result->id)
->execute();
}
db_delete('quiz_scale_user')
->condition('uid', $account->uid)
->execute();
}
/**
* Form for changing and deleting the current users preset answer collections.
*
* Users with the Edit global presets permissions can also add new global
* presets here.
*
* @param $form_state
* @return form
*/
function scale_manage_collection_form($form, &$form_state) {
global $user;
$edit_globals_access = user_access('Edit global presets');
// We create an instance of ScaleQuestion. We want to use some of its methods.
$scale_question = new ScaleQuestion(new stdClass());
$collections = $scale_question
->getPresetCollections($edit_globals_access);
// If user is allowed to edit global answer collections he is also allowed to add new global presets
if ($edit_globals_access) {
$new_col = new stdClass();
$new_col->for_all = 1;
$new_col->name = t('New global collection(available to all users)');
$collections['new'] = $new_col;
}
$form = array();
if (count($collections) == 0) {
$form['no_col'] = array(
'#markup' => t("You don't have any preset collections."),
);
return $form;
}
// Populate the form
foreach ($collections as $col_id => $obj) {
$form["collection{$col_id}"] = array(
'#type' => 'fieldset',
'#title' => $collections[$col_id]->name,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#group' => 'scale_manage_collection_form',
);
$alternatives = isset($collections[$col_id]->alternatives) ? $collections[$col_id]->alternatives : array();
for ($i = 0; $i < variable_get('scale_max_num_of_alts', 10); $i++) {
$form["collection{$col_id}"]["alternative{$i}"] = array(
'#title' => t('Alternative !i', array(
'!i' => $i + 1,
)),
'#size' => 60,
'#maxlength' => 256,
'#type' => 'textfield',
'#default_value' => isset($alternatives[$i]) ? $alternatives[$i] : '',
'#required' => $i < 2 && $col_id != 'new',
);
}
if ($col_id != 'new') {
if ($edit_globals_access) {
$form["collection{$col_id}"]['for_all'] = array(
'#type' => 'checkbox',
'#title' => t('Available to all users'),
'#default_value' => $collections[$col_id]->for_all,
);
}
$form["collection{$col_id}"]['to-do'] = array(
'#type' => 'radios',
'#title' => t('What will you do?'),
'#default_value' => '0',
'#options' => array(
t('Save changes, do not change questions using this preset'),
t('Save changes, and change your own questions who uses this preset'),
t('Delete this preset(This will not affect existing questions)'),
),
);
}
else {
$form["collection{$col_id}"]["to-do"] = array(
'#type' => 'value',
'#value' => 3,
);
$form["collection{$col_id}"]["for_all"] = array(
'#type' => 'value',
'#value' => 1,
);
}
}
$form['process'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
$form['#submit'][] = 'scale_collection_form_submit';
if ($edit_globals_access) {
$form['#validate'][] = 'scale_collection_form_validate';
}
$form['#tree'] = TRUE;
return $form;
}
/**
* Handles the scale collection form.
*
* @param $form
* @param $form_state
*/
function scale_collection_form_submit($form, &$form_state) {
global $user;
$changed = 0;
$deleted = 0;
foreach ($form_state['values'] as $key => $alternatives) {
if ($col_id = _scale_get_col_id($key)) {
$s_q = new ScaleQuestion(new stdClass());
$s_q
->initUtil($col_id);
switch ($alternatives['to-do']) {
// @todo: Rename to-do to $op
case 0:
//Save, but don't change
case 1:
//Save and change existing questions
$new_col_id = $s_q
->saveAnswerCollection(FALSE, $alternatives, 1);
if (isset($alternatives['for_all'])) {
_scale_set_for_all($new_col_id, $alternatives['for_all']);
}
if ($new_col_id == $col_id) {
break;
}
$changed++;
// We save the changes, but don't change existing questions
if ($alternatives['to-do'] == 0) {
// The old version of the collection shall not be a preset anymore
_scale_unpreset_collection($col_id, $user->uid);
// If the old version of the collection doesn't belong to any questions it is safe to delete it.
$s_q
->deleteCollectionIfNotUsed($col_id);
if (isset($alternatives['for_all'])) {
_scale_set_for_all($new_col_id, $alternatives['for_all']);
}
}
elseif ($alternatives['to-do'] == 1) {
// Update all the users questions where the collection is used
$nids = db_query('SELECT nid FROM {node} WHERE uid = :uid', array(
':uid' => 1,
))
->fetchCol();
db_update('quiz_scale_node_properties')
->fields(array(
'answer_collection_id' => $new_col_id,
))
->condition('answer_collection_id', $nids, 'IN')
->execute();
db_delete('quiz_scale_user')
->condition('answer_collection_id', $col_id)
->condition('uid', $user->uid)
->execute();
$s_q
->deleteCollectionIfNotUsed($col_id);
}
break;
case 2:
//Delete
$got_deleted = $s_q
->deleteCollectionIfNotUsed($col_id);
if (!$got_deleted) {
_scale_unpreset_collection($col_id, $user->uid);
}
$deleted++;
break;
case 3:
//New
if (drupal_strlen($alternatives['alternative0']) > 0) {
$new_col_id = $s_q
->saveAnswerCollection(FALSE, $alternatives, 1);
_scale_set_for_all($new_col_id, $alternatives['for_all']);
drupal_set_message(t('New preset has been added'));
}
break;
}
}
}
if ($changed > 0) {
drupal_set_message(t('!changed presets have been changed.', array(
'!changed' => $changed,
)));
}
if ($deleted > 0) {
drupal_set_message(t('!deleted presets have been deleted.', array(
'!deleted' => $deleted,
)));
}
}
/**
* Validates the scale collection form
*/
function scale_collection_form_validate($form, &$form_state) {
// If the user is trying to create a new collection
if (drupal_strlen($form_state['values']['collectionnew']['alternative0']) > 0) {
// If the new collection don't have two alternatives
if (drupal_strlen($form_state['values']['collectionnew']['alternative1']) == 0) {
// This can't be replaced by adding #required to the form elements. If we did so we would always have to
// create a new collection when we press submit
form_set_error('collectionnew][alternative1', t('New preset must have atleast two alternatives.'));
}
}
}
/**
* Searches a string for the answer collection id
*
* @param $string
* @return answer collection id
*/
function _scale_get_col_id($string) {
$res = array();
$success = preg_match('/^collection([0-9]{1,}|new)$/', $string, $res);
return $success > 0 ? $res[1] : FALSE;
}
/**
* Make sure an answer collection isn't a preset for a given user.
*
* @param $col_id
* Answer_collection_id
* @param $user_id
*/
function _scale_unpreset_collection($col_id, $user_id) {
db_delete('quiz_scale_user')
->condition('answer_collection_id', $col_id)
->condition('uid', $user_id)
->execute();
if (user_access('Edit global presets')) {
db_update('quiz_scale_answer_collection')
->fields(array(
'for_all' => 0,
))
->execute();
}
}
/**
* Make an answer collection (un)available for all question creators.
*
* @param $new_col_id
* Answer collection id
* @param $for_all
* 0 if not for all,
* 1 if for all
*/
function _scale_set_for_all($new_col_id, $for_all) {
db_update('quiz_scale_answer_collection')
->fields(array(
'for_all' => $for_all,
))
->condition('id', $new_col_id)
->execute();
}
Functions
Name | Description |
---|---|
scale_collection_form_submit | Handles the scale collection form. |
scale_collection_form_validate | Validates the scale collection form |
scale_config | Implements hook_config(). |
scale_config_validate | Validate the scale config form values |
scale_get_answer | Implements hook_get_answer(). |
scale_help | Implements hook_help(). |
scale_manage_collection_form | Form for changing and deleting the current users preset answer collections. |
scale_menu | Implements hook_menu(). |
scale_permission | Implements hook_permission(). |
scale_quiz_question_info | Implements hook_quiz_question_info(). |
scale_theme | Implements hook_theme(). |
scale_user_cancel | Implements hook_user_cancel(). |
_scale_get_col_id | Searches a string for the answer collection id |
_scale_set_for_all | Make an answer collection (un)available for all question creators. |
_scale_unpreset_collection | Make sure an answer collection isn't a preset for a given user. |