Skip to content
Snippets Groups Projects
Commit 7e343ffe authored by Sivaji Ganesh Jojodae's avatar Sivaji Ganesh Jojodae
Browse files

Added moodle Aiken format questions import feature

parent 098c8c22
No related branches found
No related tags found
No related merge requests found
......@@ -3,13 +3,11 @@
/**
* @file
* Questions Import
*
* Questions Import
*
* This module allows you to import questions to quiz node in CSV format.
*/
define('MAX_CSV_LINE_LENGTH', 1000);
/**
* Implementation of hook_help().
*/
......@@ -28,81 +26,81 @@ function questions_import_help($path, $arg) {
function questions_import_perm() {
return array('import_questions');
}
}
/**
* Implementation of hook_menu
*
*
*/
function questions_import_menu() {
$items = array();
function questions_import_menu() {
$items = array();
$items['admin/quiz/questions_import'] = array(
'title' => t('Import Quiz Questions'),
'description' => t('Import Questions to quiz node in CSV format'),
'page callback' => 'drupal_get_form',
'page arguments' => array('questions_import_form'),
'access arguments' => array('import_questions'),
'type' => MENU_NORMAL_ITEM,
);
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/*
* Implementation of hook_form
* form to upload questions
* form to upload questions
*/
function questions_import_form() {
$form['#attributes'] = array('enctype' => 'multipart/form-data');
$form['quiz_node'] = array(
'#type' => 'select',
'#title' => t('Quiz Node'),
'#options' => questions_import_quiz_node(),
'#title' => t('Quiz Node'),
'#options' => questions_import_quiz_node(),
'#description' => t('Select the quiz node under which you want to add questions'),
'#required' => TRUE,
);
$form['question_type'] = array(
'#type' => 'select',
'#title' => t('Question type'),
'#title' => t('Question type'),
'#options' => questions_import_question_type(),
'#description' => t('Select the quiz question type you wish to upload'),
'#description' => t('Select the quiz question type you wish to upload'),
'#required' => TRUE,
);
$form['import_type'] = array(
'#type' => 'select',
'#title' => t('Import type'),
'#title' => t('Import type'),
'#options' => questions_import_type(),
'#description' => t('Select the import type csv, XML'),
'#description' => t('Select the import type csv, XML'),
'#required' => TRUE,
);
$form['field_separator'] = array(
'#type' => 'textfield',
'#title' => t('Field Separator'),
'#title' => t('Field Separator'),
'#default_value' => t(','),
'#description' => t('Special character used to separator the fields usually , : or ; '),
'#size' => 3,
'#size' => 3,
'#required' => TRUE,
);
//'upload' will be used in file_check_upload()
//'upload' index will be used in file_check_upload()
$form['upload'] = array(
'#type' => 'file',
'#title' => t('Upload'),
'#size' => 30,
'#description' => t('Upload the file that has quiz questions'),
'#description' => t('Upload the file that has quiz questions'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('import'),
);
$form['#validate'][] = 'questions_import_form_validate';
$form['#submit'][] = 'questions_import_form_submit';
......@@ -110,10 +108,10 @@ function questions_import_form() {
}
/*
* @return
* this function return a list of quiz node title and its id.
* @return
* this function return a list of quiz node title and its id.
*/
function questions_import_quiz_node() {
$list = array();
$results = db_query("SELECT nid, title FROM {node} WHERE type = '%s'", 'quiz');
......@@ -125,7 +123,7 @@ function questions_import_quiz_node() {
}
/*
* @return
* @return
* this function return a list of available quiz questions type.
*/
......@@ -133,7 +131,7 @@ function questions_import_question_type() {
$list = array();
//checks whether the multichoice module is enabled or not.
if (module_exists('multichoice')) {
$list['multichoice'] = t('Multichoice');
$list['multichoice'] = t('Multichoice');
}
/*if (module_exists('foo_bar')) {
$list['xml'] = t('XML');
......@@ -144,69 +142,109 @@ function questions_import_question_type() {
/*
* @return
* This function is intended to return list of allowed import types CSV, XML, YML etc
*/
*/
function questions_import_type() {
return array('csv' => 'CSV');
$type = array(
'csv' => t('CSV'),
'aiken' => t('Moodle Aiken'),
);
return $type;
}
/*
*
*
* Implementation of hook_validate()
*/
function questions_import_form_validate($form, &$form_state) {
$SESSION['questions_import_start'] = microtime();
$allowed_extensions = 'csv txt';
$allowed_extensions = 'csv txt';
// it suppose to be a string which file extensions separated by space, not an array
$allowd_size = file_upload_max_size();
$field_separator = $form_state['values']['field_separator'];
$op = $form_state['values']['import_type'];
$file = file_save_upload('upload');
$file = file_save_upload('upload');
// creates a drupal file object
if (!$file) {
form_set_error('upload', 'You must select a valid file to upload.');
}
//there is a bug in Drupal file validator, refer http://api.drupal.org/api/function/file_validate_extensions it Bypass validation for uid = 1 so using custom validation functions which is same as drupal file_validate_extensions but it does not Bypass for uid = 1
else {
else {
$error_msg = question_import_validate_extensions($file, $allowed_extensions);
if($error_msg != '') {
form_set_error('upload', $error_msg);
form_set_error('upload', $error_msg);
}
$error_msg = question_import_validate_size($file, $allowd_size);
$error_msg = question_import_validate_size($file, $allowd_size);
if($error_msg != '') {
form_set_error('upload', $error_msg);
}
}
switch ($op) {
case 'csv':
$error_msg = questions_import_validate_multichoice_csv($file, $field_separator);
break;
/*case 'xml':
$error_msg = questions_import_validate_multichoice_xml($file, $field_separator);
break;*/
case 'aiken':
$error_msg = questions_import_validate_multichoice_aiken($file, $field_separator);
break;
}
if($error_msg != '') {
form_set_error('upload', $error_msg);
form_set_error('upload', $error_msg);
}
}
}
/*
* @function
* This function checks whether the aiken import file is in proper format or not.
*/
function questions_import_validate_multichoice_aiken($file, $separator) {
$error_msg = '';
$row = 0;
$lines = file($file->filepath);
if (empty($lines) || (count($lines) < 4)) {
return '<p>' . t('Invalid number of lines or no lines were found in @filename.', array('@filename' => $file->filename)) . '</p>';
}
while(!empty($lines)) { // while not empty of file content
while ($current_line = trim(array_shift($lines))) {
if (empty($current_line)) {
break;
}
$line[] = $current_line;
}
// it should have read a questions, choices and its correct answer
if (count($line) < 4) {
$error_msg .= '<p>' . t('Error around line : @line_number', array('@line_number' => $row)) . '</p>';
}
}
$answer = trim(array_pop($line));
if (stristr($answer, 'ANSWER') === FALSE) {
$error_msg .= '<p>' . t('Error around line : @line_number', array('@line_number' => $row)) . '</p>';
}
// now $line is left only with choices which looks like A) Moodle B) ATutor C) Claroline D) Blackboard etc
foreach ($line as $l) {
// yet to add validation code
}
++$row;
}
$error_msg .= !empty($error_msg) ? '<p>' . t('Aiken Import Failed. These lines were found to have an invalid number of fields in @filename.', array('@filename' => $file->filename)) . '</p>' : '';
return $error_msg;
}
/*
* @function
* This function checks whether the file has enough number of fields
* This function checks whether the csv import file is in proper format or not.
*/
function questions_import_validate_multichoice_csv($file, $separator) {
$error_msg = '';
$row = 0;
......@@ -214,98 +252,173 @@ function questions_import_validate_multichoice_csv($file, $separator) {
//reads the whole file content to an array
if (empty($lines)) {
return '<p>' . t('No lines were found in @filename.', array('@filename' => $file->filename)) . '</p>';
}
foreach ($lines as $line) {
$line = check_plain(trim($line));
}
foreach ($lines as $line) {
$line = check_plain(trim($line));
if (!empty($line)) {
++$row; // alway use pre_increment it is faster than post increment
$fields = explode($separator, $line);
$field_count = count($fields);
/* a line should have minmum of four fields i.e
/* a line should have minmum of four fields i.e
* question, option1, option2, correct option
* or maximum of 6 fields where additional two options will be option3 and option4 */
* or maximum of 6 fields where additional two options will be option3 and option4 */
if ($field_count < 4 || $field_count > 6)
$error_msg .= '<p>' . t('line : ') . $row . ' '. $line . ' </p>';
}
}
$error_msg .= !empty($error_msg) ? '<p>' . t('Import Failed. These lines were found to have an invalid number of fields in @filename.', array('@filename' => $file->filename)) . '</p>' : '';
return $error_msg;
$error_msg .= !empty($error_msg) ? '<p>' . t('CVS Import Failed. These lines were found to have an invalid number of fields in @filename.', array('@filename' => $file->filename)) . '</p>' : '';
return $error_msg;
}
function questions_import_get_microtime() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function questions_import_form_submit(&$form, &$form_state) {
$time = 0;
$op = '';
$op = '';
$quiz_nid = $form_state['values']['quiz_node'];
$op = $form_state['values']['import_type'];
$op = $form_state['values']['import_type'];
$start = questions_import_get_microtime();
switch ($op) {
case 'csv':
$count = questions_import_submit_multichoice_csv(&$form, &$form_state);
break;
/*
case 'xml':
$error_msg = questions_import_validate_multichoice_xml($file, $field_separator);
$count = questions_import_submit_multichoice_csv(&$form, &$form_state);
break;
case 'aiken':
$count = questions_import_submit_multichoice_aiken(&$form, &$form_state);
break;
*/
}
$SESSION['questions_import_end'] = microtime();
$time = $SESSION['questions_import_end'] - $SESSION['questions_import_start'];
drupal_set_message($count .' Questions were imported successfully in '. $time . ' seconds');
$time = questions_import_get_microtime() - $start;
drupal_set_message(t('@count Questions were imported successfully in @time seconds', array('@count' => $count, '@time' => $time)));
drupal_goto('node/' . $quiz_nid . '/questions');
}
function questions_import_submit_multichoice_aiken(&$form, &$form_state) {
global $user;
$row = 0;
$output = '';
$line = $options = array();
$quiz_nid = $form_state['values']['quiz_node'];
$quiz_vid = node_load($quiz_nid);
$file = file_save_upload('upload');
//creates drupal file object
$lines = file($file->filepath);
while(!empty($lines)) { // while not empty of file
while ($current_line = trim(array_shift($lines))) {
if (empty($current_line)) {
break;
}
$line[] = $current_line;
}
// read each question and its choices and correct answer.
// now $line[0] has question, $line[1 to n] has choices and $line[last] has correct answer.
$question = array_shift($line);
$answer = array_pop($line);
// now $line is left only with choices which looks like A) Moodle B) ATutor C) Claroline D) Blackboard etc
foreach ($line as $l) {
$option = explode($l[1], $l);
$options[trim($option[0])] = trim($option[1]);
}
//now $options['A'] => Moodle, $options['B'] => ATutor ...
$correct = substr(trim($answer),'-1');
$answer = $options[$correct];
$line = array();
$node = new stdClass();
$node->type = $form_state['values']['question_type']; // multichoice
$node->quiz_id = $quiz_nid;
$node->quiz_vid = $quiz_vid->vid;
$node->title = $node->body = $node->teaser = trim($question);
$node->num_answers = count($options);
$node->answers = array();
foreach ($options as $option) {
$node->answers[] = array(
'correct' => (trim($answer) == trim($option)) ? 1 : 0,
'answer' => trim($option),
'feedback' => '', //No feedback option as of now
);
}
$node->uid = $user->uid;
$node->name = $user->name;
$node->promote = 0;
$node->sticky = 0;
$node->status = 1;
$node->comment = 0;
$node->moderate = 0;
$node->multiple_answers = 0;
$node->more = 0;
$node->validate = 1;
$node->is_new = 1;
$node->format = 1;
$node->scored_quiz = 1;
$node->revision = 1;
$node->op = t('Save');
$node->preview = t('Preview');
node_save($node);
++$row;
}
return $row;
}
function questions_import_submit_multichoice_csv(&$form, &$form_state) {
global $user;
global $user;
$row = 0;
$output = '';
$quiz_nid = $form_state['values']['quiz_node'];
$quiz_vid = node_load($quiz_nid);
$file = file_save_upload('upload');
//creates drupal file object
//creates drupal file object
$lines = file($file->filepath);
$separator = $form_state['values']['field_separator'];
//print_r($lines);exit;
foreach ($lines as $line) {
$line = check_plain(trim($line));
if (!empty($line)) {
$node = new stdClass();
$node->type = $form_state['values']['question_type']; // multichoice
$node->quiz_id = $quiz_nid;
$node->quiz_vid = $quiz_vid->vid;
$line = explode($separator, $line);
$question = array_shift($line);
$answer = array_pop($line);
$options = $line;
++$row;
$node->title = $node->body = $node->teaser = trim($question);
$node->num_answers = count($options);
$node->answers = array();
foreach ($options as $option) {
$node->answers[] = array(
'correct' => (trim($answer) == trim($option)) ? 1 : 0,
'answer' => trim($option),
'feedback' => ''
);
}
$node->uid = $user->uid;
$node->name = $user->name;
$node->promote = 0;
$node->sticky = 0;
$node->status = 1;
$node->comment = 0;
$node->moderate = 0;
$node->multiple_answers = 0;
$node->more = 0;
$node->validate = 1;
$node->is_new = 1;
$node->format = 1;
$node->scored_quiz = 1;
$node->revision = 1;
$node->op = t('Save');
$node->preview = t('Preview');
node_save($node);
foreach ($lines as $line) {
$line = check_plain(trim($line));
if (empty($line)) {
continue;
}
$node = new stdClass();
$node->type = $form_state['values']['question_type']; // multichoice
$node->quiz_id = $quiz_nid;
$node->quiz_vid = $quiz_vid->vid;
$line = explode($separator, $line);
$question = array_shift($line);
$answer = array_pop($line);
$options = $line;
++$row;
$node->title = $node->body = $node->teaser = trim($question);
$node->num_answers = count($options);
$node->answers = array();
foreach ($options as $option) {
$node->answers[] = array(
'correct' => (trim($answer) == trim($option)) ? 1 : 0,
'answer' => trim($option),
'feedback' => ''
);
}
$node->uid = $user->uid;
$node->name = $user->name;
$node->promote = 0;
$node->sticky = 0;
$node->status = 1;
$node->comment = 0;
$node->moderate = 0;
$node->multiple_answers = 0;
$node->more = 0;
$node->validate = 1;
$node->is_new = 1;
$node->format = 1;
$node->scored_quiz = 1;
$node->revision = 1;
$node->op = t('Save');
$node->preview = t('Preview');
node_save($node);
}
return $row;
return $row;
}
function question_import_validate_extensions($file, $extensions){
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment