123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614 |
- <?php
- /* For licensing terms, see /license.txt */
- use ChamiloSession as Session;
- /**
- * Upload quiz: This script shows the upload quiz feature.
- */
- $help_content = 'exercise_upload';
- require_once __DIR__.'/../inc/global.inc.php';
- api_protect_course_script(true);
- $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
- $debug = false;
- $origin = api_get_origin();
- if (!$is_allowed_to_edit) {
- api_not_allowed(true);
- }
- $this_section = SECTION_COURSES;
- $htmlHeadXtra[] = "<script>
- $(function(){
- $('#user_custom_score').click(function() {
- $('#options').toggle();
- });
- });
- </script>";
- // Action handling
- lp_upload_quiz_action_handling();
- $interbreadcrumb[] = [
- 'url' => 'exercise.php?'.api_get_cidreq(),
- 'name' => get_lang('Tests'),
- ];
- Display::display_header(get_lang('Import quiz from Excel'), 'Exercises');
- echo '<div class="actions">';
- echo lp_upload_quiz_actions();
- echo '</div>';
- // the main content
- lp_upload_quiz_main();
- function lp_upload_quiz_actions()
- {
- $return = '<a href="exercise.php?'.api_get_cidreq().'">'.
- Display::return_icon(
- 'back.png',
- get_lang('BackToTestsList'),
- '',
- ICON_SIZE_MEDIUM
- ).'</a>';
- return $return;
- }
- function lp_upload_quiz_main()
- {
- $lp_id = isset($_GET['lp_id']) ? (int) $_GET['lp_id'] : null;
- $form = new FormValidator(
- 'upload',
- 'POST',
- api_get_self().'?'.api_get_cidreq().'&lp_id='.$lp_id,
- '',
- ['enctype' => 'multipart/form-data']
- );
- $form->addElement('header', get_lang('Import quiz from Excel'));
- $form->addElement('file', 'user_upload_quiz', get_lang('File upload'));
- $link = '<a href="../exercise/quiz_template.xls">'.
- Display::return_icon('export_excel.png', get_lang('Download the Excel Template')).get_lang('Download the Excel Template').'</a>';
- $form->addElement('label', '', $link);
- $table = new HTML_Table(['class' => 'table']);
- $tableList = [
- UNIQUE_ANSWER => get_lang('Multiple choice'),
- MULTIPLE_ANSWER => get_lang('Multiple answers'),
- FILL_IN_BLANKS => get_lang('Fill blanks or form'),
- MATCHING => get_lang('Matching'),
- FREE_ANSWER => get_lang('Open question'),
- GLOBAL_MULTIPLE_ANSWER => get_lang('Global multiple answer'),
- ];
- $table->setHeaderContents(0, 0, get_lang('Question type'));
- $table->setHeaderContents(0, 1, '#');
- $row = 1;
- foreach ($tableList as $key => $label) {
- $table->setCellContents($row, 0, $label);
- $table->setCellContents($row, 1, $key);
- $row++;
- }
- $table = $table->toHtml();
- $form->addElement('label', get_lang('Question type'), $table);
- $form->addElement(
- 'checkbox',
- 'user_custom_score',
- null,
- get_lang('Use custom score for all questions'),
- ['id' => 'user_custom_score']
- );
- $form->addElement('html', '<div id="options" style="display:none">');
- $form->addElement('text', 'correct_score', get_lang('Correct score'));
- $form->addElement('text', 'incorrect_score', get_lang('Incorrect score'));
- $form->addElement('html', '</div>');
- $form->addRule('user_upload_quiz', get_lang('Required field'), 'required');
- $form->addProgress();
- $form->addButtonUpload(get_lang('Upload'), 'submit_upload_quiz');
- $form->display();
- }
- /**
- * Handles a given Excel spreadsheets as in the template provided.
- */
- function lp_upload_quiz_action_handling()
- {
- if (!isset($_POST['submit_upload_quiz'])) {
- return;
- }
- $_course = api_get_course_info();
- if (empty($_course)) {
- return false;
- }
- $courseId = $_course['real_id'];
- // Get the extension of the document.
- $path_info = pathinfo($_FILES['user_upload_quiz']['name']);
- // Check if the document is an Excel document
- if (!in_array($path_info['extension'], ['xls', 'xlsx'])) {
- return;
- }
- // Variables
- $numberQuestions = 0;
- $question = [];
- $scoreList = [];
- $feedbackTrueList = [];
- $feedbackFalseList = [];
- $questionDescriptionList = [];
- $noNegativeScoreList = [];
- $questionTypeList = [];
- $answerList = [];
- $quizTitle = '';
- $objPHPExcel = PHPExcel_IOFactory::load($_FILES['user_upload_quiz']['tmp_name']);
- $objPHPExcel->setActiveSheetIndex(0);
- $worksheet = $objPHPExcel->getActiveSheet();
- $highestRow = $worksheet->getHighestRow(); // e.g. 10
- $highestColumn = $worksheet->getHighestColumn(); // e.g 'F'
- $correctScore = isset($_POST['correct_score']) ? $_POST['correct_score'] : null;
- $incorrectScore = isset($_POST['incorrect_score']) ? $_POST['incorrect_score'] : null;
- $useCustomScore = isset($_POST['user_custom_score']) ? true : false;
- for ($row = 1; $row <= $highestRow; $row++) {
- $cellTitleInfo = $worksheet->getCellByColumnAndRow(0, $row);
- $cellDataInfo = $worksheet->getCellByColumnAndRow(1, $row);
- $cellScoreInfo = $worksheet->getCellByColumnAndRow(2, $row);
- $title = $cellTitleInfo->getValue();
- switch ($title) {
- case 'Quiz':
- $quizTitle = $cellDataInfo->getValue();
- break;
- case 'Question':
- $question[] = $cellDataInfo->getValue();
- // Search cell with Answer title
- $answerRow = $row;
- $continue = true;
- $answerIndex = 0;
- while ($continue) {
- $answerRow++;
- $answerInfoTitle = $worksheet->getCellByColumnAndRow(0, $answerRow);
- $answerInfoData = $worksheet->getCellByColumnAndRow(1, $answerRow);
- $answerInfoExtra = $worksheet->getCellByColumnAndRow(2, $answerRow);
- $answerInfoTitle = $answerInfoTitle->getValue();
- if (strpos($answerInfoTitle, 'Answer') !== false) {
- $answerList[$numberQuestions][$answerIndex]['data'] = $answerInfoData->getValue();
- $answerList[$numberQuestions][$answerIndex]['extra'] = $answerInfoExtra->getValue();
- } else {
- $continue = false;
- }
- $answerIndex++;
- // To avoid loops
- if ($answerIndex > 60) {
- $continue = false;
- }
- }
- // Search cell with question type
- $answerRow = $row;
- $continue = true;
- $questionTypeIndex = 0;
- while ($continue) {
- $answerRow++;
- $questionTypeTitle = $worksheet->getCellByColumnAndRow(0, $answerRow);
- $questionTypeExtra = $worksheet->getCellByColumnAndRow(2, $answerRow);
- $title = $questionTypeTitle->getValue();
- if ($title == 'QuestionType') {
- $questionTypeList[$numberQuestions] = $questionTypeExtra->getValue();
- $continue = false;
- }
- if ($title == 'Question') {
- $continue = false;
- }
- // To avoid loops
- if ($questionTypeIndex > 60) {
- $continue = false;
- }
- $questionTypeIndex++;
- }
- // Detect answers
- $numberQuestions++;
- break;
- case 'Score':
- $scoreList[] = $cellScoreInfo->getValue();
- break;
- case 'NoNegativeScore':
- $noNegativeScoreList[] = $cellScoreInfo->getValue();
- break;
- case 'Category':
- $categoryList[] = $cellDataInfo->getValue();
- break;
- case 'FeedbackTrue':
- $feedbackTrueList[] = $cellDataInfo->getValue();
- break;
- case 'FeedbackFalse':
- $feedbackFalseList[] = $cellDataInfo->getValue();
- break;
- case 'EnrichQuestion':
- $questionDescriptionList[] = $cellDataInfo->getValue();
- break;
- }
- }
- $propagateNegative = 0;
- if ($useCustomScore && !empty($incorrectScore)) {
- if ($incorrectScore < 0) {
- $propagateNegative = 1;
- }
- }
- if ($quizTitle != '') {
- // Variables
- $type = 2;
- $random = $active = $results = $max_attempt = $expired_time = 0;
- // Make sure feedback is enabled (3 to disable), otherwise the fields
- // added to the XLS are not shown, which is confusing
- $feedback = 0;
- // Quiz object
- $exercise = new Exercise();
- $exercise->updateTitle($quizTitle);
- $exercise->updateExpiredTime($expired_time);
- $exercise->updateType($type);
- $exercise->setRandom($random);
- $exercise->active = $active;
- $exercise->updateResultsDisabled($results);
- $exercise->updateAttempts($max_attempt);
- $exercise->updateFeedbackType($feedback);
- $exercise->updatePropagateNegative($propagateNegative);
- $quiz_id = $exercise->save();
- if ($quiz_id) {
- // Import questions.
- for ($i = 0; $i < $numberQuestions; $i++) {
- // Question name
- $questionTitle = $question[$i];
- $myAnswerList = isset($answerList[$i]) ? $answerList[$i] : [];
- $description = isset($questionDescriptionList[$i]) ? $questionDescriptionList[$i] : '';
- $categoryId = null;
- if (isset($categoryList[$i]) && !empty($categoryList[$i])) {
- $categoryName = $categoryList[$i];
- $categoryId = TestCategory::get_category_id_for_title($categoryName, $courseId);
- if (empty($categoryId)) {
- $category = new TestCategory();
- $category->name = $categoryName;
- $categoryId = $category->save();
- }
- }
- $question_description_text = '<p></p>';
- if (!empty($description)) {
- // Question description.
- $question_description_text = "<p>$description</p>";
- }
- // Unique answers are the only question types available for now
- // through xls-format import
- $question_id = null;
- if (isset($questionTypeList[$i]) && $questionTypeList[$i] != '') {
- $detectQuestionType = (int) $questionTypeList[$i];
- } else {
- $detectQuestionType = detectQuestionType($myAnswerList);
- }
- /** @var Question $answer */
- switch ($detectQuestionType) {
- case FREE_ANSWER:
- $answer = new FreeAnswer();
- break;
- case GLOBAL_MULTIPLE_ANSWER:
- $answer = new GlobalMultipleAnswer();
- break;
- case MULTIPLE_ANSWER:
- $answer = new MultipleAnswer();
- break;
- case FILL_IN_BLANKS:
- $answer = new FillBlanks();
- $question_description_text = '';
- break;
- case MATCHING:
- $answer = new Matching();
- break;
- case UNIQUE_ANSWER:
- default:
- $answer = new UniqueAnswer();
- break;
- }
- if ($questionTitle != '') {
- $question_id = $answer->create_question(
- $quiz_id,
- $questionTitle,
- $question_description_text,
- 0, // max score
- $answer->type
- );
- if (!empty($categoryId)) {
- TestCategory::addCategoryToQuestion(
- $categoryId,
- $question_id,
- $courseId
- );
- }
- }
- switch ($detectQuestionType) {
- case GLOBAL_MULTIPLE_ANSWER:
- case MULTIPLE_ANSWER:
- case UNIQUE_ANSWER:
- $total = 0;
- if (is_array($myAnswerList) && !empty($myAnswerList) && !empty($question_id)) {
- $id = 1;
- $objAnswer = new Answer($question_id, $courseId);
- $globalScore = isset($scoreList[$i]) ? $scoreList[$i] : null;
- // Calculate the number of correct answers to divide the
- // score between them when importing from CSV
- $numberRightAnswers = 0;
- foreach ($myAnswerList as $answer_data) {
- if (strtolower($answer_data['extra']) == 'x') {
- $numberRightAnswers++;
- }
- }
- foreach ($myAnswerList as $answer_data) {
- $answerValue = $answer_data['data'];
- $correct = 0;
- $score = 0;
- if (strtolower($answer_data['extra']) == 'x') {
- $correct = 1;
- $score = isset($scoreList[$i]) ? $scoreList[$i] : 0;
- $comment = isset($feedbackTrueList[$i]) ? $feedbackTrueList[$i] : '';
- } else {
- $comment = isset($feedbackFalseList[$i]) ? $feedbackFalseList[$i] : '';
- $floatVal = (float) $answer_data['extra'];
- if (is_numeric($floatVal)) {
- $score = $answer_data['extra'];
- }
- }
- if ($useCustomScore) {
- if ($correct) {
- $score = $correctScore;
- } else {
- $score = $incorrectScore;
- }
- }
- // Fixing scores:
- switch ($detectQuestionType) {
- case GLOBAL_MULTIPLE_ANSWER:
- if ($correct) {
- $score = abs($scoreList[$i]);
- } else {
- if (isset($noNegativeScoreList[$i]) && $noNegativeScoreList[$i] == 'x') {
- $score = 0;
- } else {
- $score = -abs($scoreList[$i]);
- }
- }
- $score /= $numberRightAnswers;
- break;
- case UNIQUE_ANSWER:
- break;
- case MULTIPLE_ANSWER:
- if (!$correct) {
- //$total = $total - $score;
- }
- break;
- }
- $objAnswer->createAnswer(
- $answerValue,
- $correct,
- $comment,
- $score,
- $id
- );
- $total += (float) $score;
- $id++;
- }
- $objAnswer->save();
- $questionObj = Question::read(
- $question_id,
- $_course
- );
- if ($questionObj) {
- switch ($detectQuestionType) {
- case GLOBAL_MULTIPLE_ANSWER:
- $questionObj->updateWeighting($globalScore);
- break;
- case UNIQUE_ANSWER:
- case MULTIPLE_ANSWER:
- default:
- $questionObj->updateWeighting($total);
- break;
- }
- $questionObj->save($exercise);
- }
- }
- break;
- case FREE_ANSWER:
- $globalScore = isset($scoreList[$i]) ? $scoreList[$i] : null;
- $questionObj = Question::read($question_id, $_course);
- if ($questionObj) {
- $questionObj->updateWeighting($globalScore);
- $questionObj->save($exercise);
- }
- break;
- case FILL_IN_BLANKS:
- $fillInScoreList = [];
- $size = [];
- $globalScore = 0;
- foreach ($myAnswerList as $data) {
- $score = isset($data['extra']) ? $data['extra'] : 0;
- $globalScore += $score;
- $fillInScoreList[] = $score;
- $size[] = 200;
- }
- $scoreToString = implode(',', $fillInScoreList);
- $sizeToString = implode(',', $size);
- //<p>Texte long avec les [mots] à [remplir] mis entre [crochets]</p>::10,10,10:200.36363999999998,200,200:0@'
- $answerValue = $description.'::'.$scoreToString.':'.$sizeToString.':0@';
- $objAnswer = new Answer($question_id, $courseId);
- $objAnswer->createAnswer(
- $answerValue,
- '', //$correct,
- '', //$comment,
- $globalScore,
- 1
- );
- $objAnswer->save();
- $questionObj = Question::read($question_id, $_course);
- if ($questionObj) {
- $questionObj->updateWeighting($globalScore);
- $questionObj->save($exercise);
- }
- break;
- case MATCHING:
- $globalScore = isset($scoreList[$i]) ? $scoreList[$i] : null;
- $position = 1;
- $objAnswer = new Answer($question_id, $courseId);
- foreach ($myAnswerList as $data) {
- $option = isset($data['extra']) ? $data['extra'] : '';
- $objAnswer->createAnswer($option, 0, '', 0, $position);
- $position++;
- }
- $counter = 1;
- foreach ($myAnswerList as $data) {
- $value = isset($data['data']) ? $data['data'] : '';
- $position++;
- $objAnswer->createAnswer(
- $value,
- $counter,
- ' ',
- $globalScore,
- $position
- );
- $counter++;
- }
- $objAnswer->save();
- $questionObj = Question::read($question_id, $_course);
- if ($questionObj) {
- $questionObj->updateWeighting($globalScore);
- $questionObj->save($exercise);
- }
- break;
- }
- }
- }
- $lpObject = Session::read('lpobject');
- if (!empty($lpObject)) {
- /** @var learnpath $oLP */
- $oLP = UnserializeApi::unserialize('lp', $lpObject);
- if (is_object($oLP)) {
- if ((empty($oLP->cc)) || $oLP->cc != api_get_course_id()) {
- $oLP = null;
- Session::erase('oLP');
- Session::erase('lpobject');
- } else {
- Session::write('oLP', $oLP);
- }
- }
- }
- if (isset($_SESSION['oLP']) && isset($_GET['lp_id'])) {
- $previous = $_SESSION['oLP']->select_previous_item_id();
- $parent = 0;
- // Add a Quiz as Lp Item
- $_SESSION['oLP']->add_item(
- $parent,
- $previous,
- TOOL_QUIZ,
- $quiz_id,
- $quizTitle,
- ''
- );
- // Redirect to home page for add more content
- header('Location: ../lp/lp_controller.php?'.api_get_cidreq().'&action=add_item&type=step&lp_id='.intval($_GET['lp_id']));
- exit;
- } else {
- // header('location: exercise.php?' . api_get_cidreq());
- echo '<script>window.location.href = "'.api_get_path(WEB_CODE_PATH).'exercise/admin.php?'.api_get_cidreq().'&exerciseId='.$quiz_id.'&session_id='.api_get_session_id().'"</script>';
- }
- }
- }
- /**
- * @param array $answers_data
- *
- * @return int
- */
- function detectQuestionType($answers_data)
- {
- $correct = 0;
- $isNumeric = false;
- if (empty($answers_data)) {
- return FREE_ANSWER;
- }
- foreach ($answers_data as $answer_data) {
- if (strtolower($answer_data['extra']) == 'x') {
- $correct++;
- } else {
- if (is_numeric($answer_data['extra'])) {
- $isNumeric = true;
- }
- }
- }
- if ($correct == 1) {
- $type = UNIQUE_ANSWER;
- } else {
- if ($correct > 1) {
- $type = MULTIPLE_ANSWER;
- } else {
- $type = FREE_ANSWER;
- }
- }
- if ($type == MULTIPLE_ANSWER) {
- if ($isNumeric) {
- $type = MULTIPLE_ANSWER;
- } else {
- $type = GLOBAL_MULTIPLE_ANSWER;
- }
- }
- return $type;
- }
- if ($origin != 'learnpath') {
- //so we are not in learnpath tool
- Display::display_footer();
- }
|