* @version $Id: exercise.lib.php 22247 2009-07-20 15:57:25Z ivantcholakov $
*/
/**
* Code
*/
// The initialization class for the online editor is needed here.
require_once dirname(__FILE__).'/../inc/lib/fckeditor/fckeditor.php';
/**
* Shows a question
*
* @param int question id
* @param bool if true only show the questions, no exercise title
* @param bool origin i.e = learnpath
* @param int current item from the list of questions
* @param int number of total questions
* */
function showQuestion($questionId, $only_questions = false, $origin = false, $current_item = '', $show_title = true, $freeze = false, $user_choice = array()) {
// Text direction for the current language
$is_ltr_text_direction = api_get_text_direction() != 'rtl';
$remind_question = 1;
// Change false to true in the following line to enable answer hinting.
$debug_mark_answer = api_is_allowed_to_edit() && false;
// Reads question information
if (!$objQuestionTmp = Question::read($questionId)) {
// Question not found
return false;
}
$answerType = $objQuestionTmp->selectType();
$pictureName = $objQuestionTmp->selectPicture();
$html = '';
if ($answerType != HOT_SPOT && $answerType != HOT_SPOT_DELINEATION) {
// Question is not a hotspot
if (!$only_questions) {
$questionDescription = $objQuestionTmp->selectDescription();
if ($show_title) {
echo Display::div($current_item.'. '.$objQuestionTmp->selectTitle(), array('class'=>'question_title'));
}
if (!empty($questionDescription)) {
echo Display::div($questionDescription, array('class'=>'question_description'));
}
//@deprecated
if (!empty($pictureName)) {
//echo "";
}
}
echo '
';
// construction of the Answer object (also gets all answers details)
$objAnswerTmp = new Answer($questionId);
$nbrAnswers = $objAnswerTmp->selectNbrAnswers();
$quiz_question_options = Question::readQuestionOption($questionId);
// For "matching" type here, we need something a little bit special
// because the match between the suggestions and the answers cannot be
// done easily (suggestions and answers are in the same table), so we
// have to go through answers first (elems with "correct" value to 0).
$select_items = array();
//This will contain the number of answers on the left side. We call them
// suggestions here, for the sake of comprehensions, while the ones
// on the right side are called answers
$num_suggestions = 0;
if ($answerType == MATCHING) {
$x = 1; //iterate through answers
$letter = 'A'; //mark letters for each answer
$answer_matching = $cpt1 = array();
$answer_suggestions = $nbrAnswers;
for ($answerId=1; $answerId <= $nbrAnswers; $answerId++) {
$answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId);
$answer=$objAnswerTmp->selectAnswer($answerId);
if ($answerCorrect==0) {
// options (A, B, C, ...) that will be put into the list-box
// have the "correct" field set to 0 because they are answer
$cpt1[$x] = $letter;
$answer_matching[$x]=$objAnswerTmp->selectAnswerByAutoId($numAnswer);
$x++; $letter++;
}
}
$i = 1;
$select_items[0]['id'] = 0;
$select_items[0]['letter'] = '--';
$select_items[0]['answer'] = '';
foreach ($answer_matching as $id => $value) {
$select_items[$i]['id'] = $value['id'];
$select_items[$i]['letter'] = $cpt1[$id];
$select_items[$i]['answer'] = $value['answer'];
$i ++;
}
$num_suggestions = ($nbrAnswers - $x) + 1;
} elseif ($answerType == FREE_ANSWER) {
$fck_content = isset($user_choice[0]) && !empty($user_choice[0]['answer']) ? $user_choice[0]['answer']:null;
$oFCKeditor = new FCKeditor("choice[".$questionId."]") ;
$oFCKeditor->ToolbarSet = 'TestFreeAnswer';
$oFCKeditor->Width = '100%';
$oFCKeditor->Height = '200';
$oFCKeditor->Value = $fck_content;
$s .= '
';
$s .= $oFCKeditor->CreateHtml();
$s .= '
';
}
// Now navigate through the possible answers, using the max number of
// answers for the question as a limiter
$lines_count = 1; // a counter for matching-type answers
$question_list = array();
if ($answerType == MULTIPLE_ANSWER_TRUE_FALSE || $answerType == MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE) {
$header .= Display::tag('th', get_lang('Options'));
foreach ($objQuestionTmp->options as $key=>$item) {
$header .= Display::tag('th', $item);
}
$s.= Display::tag('tr',$header, array('style'=>'text-align:left;'));
}
$matching_correct_answer = 0;
$user_choice_array = array();
if (!empty($user_choice)) {
foreach($user_choice as $item) {
$user_choice_array[] = $item['answer'];
}
}
for ($answerId=1; $answerId <= $nbrAnswers; $answerId++) {
$answer = $objAnswerTmp->selectAnswer($answerId);
$answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId);
// Unique answer
if ($answerType == UNIQUE_ANSWER || $answerType == UNIQUE_ANSWER_NO_OPTION) {
// set $debug_mark_answer to true at function start to
// show the correct answer with a suffix '-x'
$help = $selected = '';
if ($debug_mark_answer) {
if ($answerCorrect) {
$help = 'x-';
$selected = 'checked';
}
}
$input_id = 'choice-'.$questionId.'-'.$answerId;
if (isset($user_choice[0]['answer']) && $user_choice[0]['answer'] == $numAnswer ) {
$attributes = array('id' =>$input_id, 'class'=>'checkbox','checked'=>1, 'selected'=>1);
} else {
$attributes = array('id' =>$input_id, 'class'=>'checkbox');
}
$answer = Security::remove_XSS($answer, STUDENT);
$s .= Display::input('hidden','choice2['.$questionId.']','0');
//@todo fix $is_ltr_text_direction
//
';
} elseif ($answerType == FILL_IN_BLANKS) {
/*
// splits text and weightings that are joined with the character '::'
list($answer) = explode('::',$answer);
//getting the matches
$answer = api_ereg_replace('\[[^]]+\]','',($answer));
$answer = api_preg_replace('/\[[^]]+\]/', Display::input('text', "choice[$questionId][]", '', $attributes), $answer);
api_preg_match_all('/\[[^]]+\]/', $answer, $fill_list);
if (isset($user_choice[0]['answer'])) {
api_preg_match_all('/\[[^]]+\]/', $user_choice[0]['answer'], $user_fill_list);
$user_fill_list = $user_fill_list[0];
}*/
list($answer) = explode('::',$answer);
api_preg_match_all('/\[[^]]+\]/', $answer, $teacher_answer_list);
if (isset($user_choice[0]['answer'])) {
api_preg_match_all('/\[[^]]+\]/', $user_choice[0]['answer'], $student_answer_list);
$student_answer_list = $student_answer_list[0];
}
//var_dump($teacher_answer_list, $student_answer_list);
if (!empty($teacher_answer_list) && !empty($student_answer_list)) {
$teacher_answer_list = $teacher_answer_list[0];
$i = 0;
foreach($teacher_answer_list as $teacher_item) {
$value = null;
if (isset($student_answer_list[$i]) && !empty($student_answer_list[$i])) {
//Cleaning student answer list
$value = strip_tags($student_answer_list[$i]);
$value = api_substr($value,1, api_strlen($value)-2);
$value = explode('/', $value);
if (!empty($value[0])) {
$value = trim($value[0]);
$value = str_replace(' ', '', $value);
}
$answer = api_preg_replace('/\['.$teacher_item.'+\]/', Display::input('text', "choice[$questionId][]", $value), $answer);
}
$i++;
}
} else {
$answer = api_preg_replace('/\[[^]]+\]/', Display::input('text', "choice[$questionId][]", '', $attributes), $answer);
}
$s .= '
'.$answer.'
';
} elseif ($answerType == MATCHING) {
// matching type, showing suggestions and answers
// TODO: replace $answerId by $numAnswer
if ($answerCorrect != 0) {
// only show elements to be answered (not the contents of
// the select boxes, who are corrrect = 0)
$s .= '
';
$lines_count++;
//if the left side of the "matching" has been completely
// shown but the right side still has values to show...
if (($lines_count -1) == $num_suggestions) {
// if it remains answers to shown at the right side
while (isset($select_items[$lines_count])) {
$s .= '
";
$lines_count++;
} // end while()
} // end if()
$matching_correct_answer++;
}
}
} // end for()
$s .= '
';
$s .= '';
// destruction of the Answer object
unset($objAnswerTmp);
// destruction of the Question object
unset($objQuestionTmp);
if ($origin != 'export') {
echo $s;
} else {
return $s;
}
} elseif ($answerType == HOT_SPOT || $answerType == HOT_SPOT_DELINEATION) {
// Question is a HOT_SPOT
//checking document/images visibility
if (api_is_platform_admin() || api_is_course_admin()) {
require_once api_get_path(LIBRARY_PATH).'document.lib.php';
$course = api_get_course_info();
$doc_id = DocumentManager::get_document_id($course, '/images/'.$pictureName);
if (is_numeric($doc_id)) {
$images_folder_visibility = api_get_item_visibility($course,'document', $doc_id, api_get_session_id());
if (!$images_folder_visibility) {
//This message is shown only to the course/platform admin if the image is set to visibility = false
Display::display_warning_message(get_lang('ChangeTheVisibilityOfTheCurrentImage'));
}
}
}
$questionName = $objQuestionTmp->selectTitle();
$questionDescription = $objQuestionTmp->selectDescription();
if ($freeze) {
echo Display::img($objQuestionTmp->selectPicturePath());
return;
}
// Get the answers, make a list
$objAnswerTmp = new Answer($questionId);
$nbrAnswers = $objAnswerTmp->selectNbrAnswers();
// get answers of hotpost
$answers_hotspot = array();
for ($answerId=1;$answerId <= $nbrAnswers;$answerId++) {
$answers = $objAnswerTmp->selectAnswerByAutoId($objAnswerTmp->selectAutoId($answerId));
$answers_hotspot[$answers['id']] = $objAnswerTmp->selectAnswer($answerId);
}
// display answers of hotpost order by id
$answer_list = '
'.get_lang('HotspotZones').'
';
if (!empty($answers_hotspot)) {
ksort($answers_hotspot);
foreach ($answers_hotspot as $key => $value) {
$answer_list .= '