@ -1,11 +1,11 @@
<?php
/* For licensing terms, see /license.txt */
/**
* File containing the Question class.
* File containing the Question class.
* @package chamilo.exercise
* @author Olivier Brouckaert
* @author Julio Montoya < gugli100 @ gmail . com > lot of bug fixes
* Modified by hubert.borderiou@grenet.fr - add question categories
* Modified by hubert.borderiou@grenet.fr - add question categories
*/
/**
* Code
@ -67,25 +67,22 @@ abstract class Question
public $editionMode = 'normal';
static $questionTypes = array(
UNIQUE_ANSWER => array('unique_answer.class.php', 'UniqueAnswer'),
MULTIPLE_ANSWER => array('multiple_answer.class.php', 'MultipleAnswer'),
FILL_IN_BLANKS => array('fill_blanks.class.php', 'FillBlanks'),
MATCHING => array('matching.class.php', 'Matching'),
FREE_ANSWER => array('freeanswer.class.php', 'FreeAnswer'),
ORAL_EXPRESSION => array('oral_expression.class.php', 'OralExpression'),
HOT_SPOT => array('hotspot.class.php', 'HotSpot'),
HOT_SPOT_DELINEATION => array('hotspot.class.php', 'HotspotDelineation'),
MULTIPLE_ANSWER_COMBINATION => array('multiple_answer_combination.class.php', 'MultipleAnswerCombination'),
UNIQUE_ANSWER_NO_OPTION => array('unique_answer_no_option.class.php', 'UniqueAnswerNoOption'),
MULTIPLE_ANSWER_TRUE_FALSE => array('multiple_answer_true_false.class.php', 'MultipleAnswerTrueFalse'),
MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE => array(
'multiple_answer_combination_true_false.class.php',
'MultipleAnswerCombinationTrueFalse'
),
GLOBAL_MULTIPLE_ANSWER => array('global_multiple_answer.class.php', 'GlobalMultipleAnswer'),
MEDIA_QUESTION => array('media_question.class.php', 'MediaQuestion'),
UNIQUE_ANSWER_IMAGE => array('unique_answer_image.class.php', 'UniqueAnswerImage'),
DRAGGABLE => array('draggable.class.php', 'Draggable')
UNIQUE_ANSWER => array('unique_answer.class.php', 'UniqueAnswer'),
MULTIPLE_ANSWER => array('multiple_answer.class.php', 'MultipleAnswer'),
FILL_IN_BLANKS => array('fill_blanks.class.php', 'FillBlanks'),
MATCHING => array('matching.class.php', 'Matching'),
FREE_ANSWER => array('freeanswer.class.php', 'FreeAnswer'),
ORAL_EXPRESSION => array('oral_expression.class.php', 'OralExpression'),
HOT_SPOT => array('hotspot.class.php', 'HotSpot'),
HOT_SPOT_DELINEATION => array('hotspot.class.php', 'HotspotDelineation'),
MULTIPLE_ANSWER_COMBINATION => array('multiple_answer_combination.class.php', 'MultipleAnswerCombination' ),
UNIQUE_ANSWER_NO_OPTION => array('unique_answer_no_option.class.php', 'UniqueAnswerNoOption'),
MULTIPLE_ANSWER_TRUE_FALSE => array('multiple_answer_true_false.class.php', 'MultipleAnswerTrueFalse'),
MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE => array('multiple_answer_combination_true_false.class.php', 'MultipleAnswerCombinationTrueFalse'),
GLOBAL_MULTIPLE_ANSWER => array('global_multiple_answer.class.php', 'GlobalMultipleAnswer'),
MEDIA_QUESTION => array('media_question.class.php', 'MediaQuestion'),
UNIQUE_ANSWER_IMAGE => array('unique_answer_image.class.php', 'UniqueAnswerImage'),
DRAGGABLE => array('draggable.class.php', 'Draggable')
);
/**
@ -95,19 +92,19 @@ abstract class Question
*/
public function Question()
{
$this->id = 0;
$this->question = '';
$this->description = '';
$this->weighting = 0;
$this->position = 1;
$this->picture = '';
$this->level = 1;
$this->extra = ''; // This variable is used when loading an exercise like an scenario with an special hotspot: final_overlap, final_missing, final_excess
$this->exerciseList = array();
$this->course = api_get_course_info();
$this->id = 0;
$this->question = '';
$this->description = '';
$this->weighting = 0;
$this->position = 1;
$this->picture = '';
$this->level = 1;
$this->extra = ''; // This variable is used when loading an exercise like an scenario with an special hotspot: final_overlap, final_missing, final_excess
$this->exerciseList = array();
$this->course = api_get_course_info();
$this->category_list = array();
$this->parent_id = 0;
$this->editionMode = 'normal';
$this->parent_id = 0;
$this->editionMode = 'normal';
}
public function getIsContent()
@ -122,10 +119,11 @@ abstract class Question
/**
* @param string $title
* @param int $course_id
* @param int $course_id
* @return mixed|bool
*/
public function readByTitle($title, $course_id = null) {
public function readByTitle($title, $course_id = null)
{
if (!empty($course_id)) {
$course_info = api_get_course_info_by_id($course_id);
} else {
@ -134,13 +132,15 @@ abstract class Question
$course_id = $course_info['real_id'];
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$title = Database::escape_string($title);
$sql = "SELECT iid FROM $TBL_QUESTIONS WHERE question = '$title' AND c_id = $course_id ";
$result = Database::query($sql);
$title = Database::escape_string($title);
$sql = "SELECT iid FROM $TBL_QUESTIONS WHERE question = '$title' AND c_id = $course_id ";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$row = Database::fetch_array($result);
return self::read($row['iid'], $course_id);
}
return false;
}
@ -167,7 +167,7 @@ abstract class Question
return false;
}
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$sql = "SELECT * FROM $TBL_QUESTIONS WHERE iid = $id AND c_id = $course_id";
@ -180,20 +180,20 @@ abstract class Question
$objQuestion = Question::getInstance($object->type);
if (!empty($objQuestion)) {
$objQuestion->id = $id;
$objQuestion->question = $object->question;
$objQuestion->description = $object->description;
$objQuestion->weighting = $object->ponderation;
$objQuestion->position = $object->position;
$objQuestion->type = $object->type;
$objQuestion->picture = $object->picture;
$objQuestion->level = (int)$object->level;
$objQuestion->extra = $object->extra;
$objQuestion->course = $course_info;
$objQuestion->parent_id = $object->parent_id;
$objQuestion->id = $id;
$objQuestion->question = $object->question;
$objQuestion->description = $object->description;
$objQuestion->weighting = $object->ponderation;
$objQuestion->position = $object->position;
$objQuestion->type = $object->type;
$objQuestion->picture = $object->picture;
$objQuestion->level = (int)$object->level;
$objQuestion->extra = $object->extra;
$objQuestion->course = $course_info;
$objQuestion->parent_id = $object->parent_id;
$objQuestion->category_list = Testcategory::getCategoryForQuestion($id);
$sql = "SELECT exercice_id FROM $TBL_EXERCICE_QUESTION WHERE c_id = $course_id AND question_id = $id";
$sql = "SELECT exercice_id FROM $TBL_EXERCICE_QUESTION WHERE c_id = $course_id AND question_id = $id";
$result_exercise_list = Database::query($sql);
// fills the array with the exercises which this question is in
@ -349,6 +349,7 @@ abstract class Question
{
$this->course = api_get_course_info_by_id($course_id);
}
/**
* changes the question title
*
@ -423,13 +424,14 @@ abstract class Question
* @param - int $in_positive
* @author - Julio Montoya - Adding multiple cat support
*/
function saveCategories($category_list) {
function saveCategories($category_list)
{
$course_id = $this->course['real_id'];
if (!empty($category_list)) {
$this->deleteCategory();
$TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
$category_list = array_filter($category_list);
$category_list = array_filter($category_list);
// update or add category for a question
foreach ($category_list as $category_id) {
@ -438,9 +440,9 @@ abstract class Question
}
$category_id = intval($category_id);
$question_id = Database::escape_string($this->id);
$sql = "SELECT count(*) AS nb FROM $TBL_QUESTION_REL_CATEGORY WHERE category_id = $category_id AND question_id = $question_id AND c_id=".$course_id;
$res = Database::query($sql);
$row = Database::fetch_array($res);
$sql = "SELECT count(*) AS nb FROM $TBL_QUESTION_REL_CATEGORY WHERE category_id = $category_id AND question_id = $question_id AND c_id=".$course_id;
$res = Database::query($sql);
$row = Database::fetch_array($res);
if ($row['nb'] > 0) {
//DO nothing
//$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id = $category_id WHERE question_id=$question_id AND c_id=".api_get_course_int_id();
@ -467,16 +469,19 @@ abstract class Question
// update or add category for a question
$TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
$category_id = Database::escape_string($in_category);
$question_id = Database::escape_string($this->id);
$sql = "SELECT count(*) AS nb FROM $TBL_QUESTION_REL_CATEGORY WHERE question_id= $question_id AND c_id=".api_get_course_int_id();
$res = Database::query($sql);
$row = Database::fetch_array($res);
$category_id = Database::escape_string($in_category);
$question_id = Database::escape_string($this->id);
$sql = "SELECT count(*) AS nb FROM $TBL_QUESTION_REL_CATEGORY WHERE question_id= $question_id AND c_id=".api_get_course_int_id(
);
$res = Database::query($sql);
$row = Database::fetch_array($res);
if ($row['nb'] > 0) {
$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id= $category_id WHERE question_id=$question_id AND c_id=".api_get_course_int_id();
$sql = "UPDATE $TBL_QUESTION_REL_CATEGORY SET category_id= $category_id WHERE question_id=$question_id AND c_id=".api_get_course_int_id(
);
$res = Database::query($sql);
} else {
$sql = "INSERT INTO $TBL_QUESTION_REL_CATEGORY VALUES (".api_get_course_int_id().", $question_id, $category_id)";
$sql = "INSERT INTO $TBL_QUESTION_REL_CATEGORY VALUES (".api_get_course_int_id(
).", $question_id, $category_id)";
$res = Database::query($sql);
}
}
@ -488,11 +493,12 @@ abstract class Question
* @param : none
* delte the category for question
*/
function deleteCategory() {
$course_id = $this->course['real_id'];
function deleteCategory()
{
$course_id = $this->course['real_id'];
$TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
$question_id = Database::escape_string($this->id);
$sql = "DELETE FROM $TBL_QUESTION_REL_CATEGORY WHERE question_id = $question_id AND c_id = ".$course_id;
$question_id = Database::escape_string($this->id);
$sql = "DELETE FROM $TBL_QUESTION_REL_CATEGORY WHERE question_id = $question_id AND c_id = ".$course_id;
Database::query($sql);
}
@ -528,7 +534,7 @@ abstract class Question
function updateType($type)
{
$TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER);
$course_id = $this->course['real_id'];
$course_id = $this->course['real_id'];
if (empty($course_id)) {
$course_id = api_get_course_int_id();
@ -570,18 +576,18 @@ abstract class Question
if (mkdir($picturePath, api_get_permissions_for_new_directories())) {
// document path
$documentPath = api_get_path(SYS_COURSE_PATH).$this->course['path']."/document";
$path = str_replace($documentPath, '', $picturePath);
$title_path = basename($picturePath);
$doc_id = FileManager::add_document($this->course, $path, 'folder', 0, $title_path);
$path = str_replace($documentPath, '', $picturePath);
$title_path = basename($picturePath);
$doc_id = FileManager::add_document($this->course, $path, 'folder', 0, $title_path);
api_item_property_update($this->course, TOOL_DOCUMENT, $doc_id, 'FolderCreated', api_get_user_id());
}
}
// if the question has got an ID
if ($this->id) {
$extension = pathinfo($PictureName, PATHINFO_EXTENSION);
$extension = pathinfo($PictureName, PATHINFO_EXTENSION);
$this->picture = 'quiz-'.$this->id.'.jpg';
$o_img = new Image($Picture);
$o_img = new Image($Picture);
$o_img->send_image($picturePath.'/'.$this->picture, -1, 'jpg');
$document_id = FileManager::add_document(
$this->course,
@ -622,8 +628,8 @@ abstract class Question
$my_image = new Image($picturePath.'/'.$this->picture);
$current_image_size = $my_image->get_image_size();
$current_width = $current_image_size['width'];
$current_height = $current_image_size['height'];
$current_width = $current_image_size['width'];
$current_height = $current_image_size['height'];
if ($current_width < $Max & & $current_height < $Max) {
return true;
@ -634,28 +640,28 @@ abstract class Question
// Resize according to height.
if ($Dimension == "height") {
$resize_scale = $current_height / $Max;
$new_height = $Max;
$new_width = ceil($current_width / $resize_scale);
$new_height = $Max;
$new_width = ceil($current_width / $resize_scale);
}
// Resize according to width
if ($Dimension == "width") {
$resize_scale = $current_width / $Max;
$new_width = $Max;
$new_height = ceil($current_height / $resize_scale);
$new_width = $Max;
$new_height = ceil($current_height / $resize_scale);
}
// Resize according to height or width, both should not be larger than $Max after resizing.
if ($Dimension == "any") {
if ($current_height > $current_width || $current_height == $current_width) {
$resize_scale = $current_height / $Max;
$new_height = $Max;
$new_width = ceil($current_width / $resize_scale);
$new_height = $Max;
$new_width = ceil($current_width / $resize_scale);
}
if ($current_height < $current_width) {
$resize_scale = $current_width / $Max;
$new_width = $Max;
$new_height = ceil($current_height / $resize_scale);
$new_width = $Max;
$new_height = ceil($current_height / $resize_scale);
}
}
@ -682,7 +688,7 @@ abstract class Question
// if the question has got an ID and if the picture exists
if ($this->id) {
$picture = $this->picture;
$picture = $this->picture;
$this->picture = '';
return @unlink($picturePath.'/'.$picture) ? true : false;
@ -700,17 +706,17 @@ abstract class Question
*/
function exportPicture($questionId, $course_info)
{
$course_id = $course_info['real_id'];
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$course_id = $course_info['real_id'];
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$destination_path = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document/images';
$source_path = api_get_path(SYS_COURSE_PATH).$this->course['path'].'/document/images';
$source_path = api_get_path(SYS_COURSE_PATH).$this->course['path'].'/document/images';
// if the question has got an ID and if the picture exists
if ($this->id & & !empty($this->picture)) {
$picture = explode('.', $this->picture);
$picture = explode('.', $this->picture);
$extension = $picture[sizeof($picture) - 1];
$picture = 'quiz-'.$questionId.'.'.$extension;
$result = @copy($source_path.'/'.$this->picture, $destination_path.'/'.$picture) ? true : false;
$picture = 'quiz-'.$questionId.'.'.$extension;
$result = @copy($source_path.'/'.$this->picture, $destination_path.'/'.$picture) ? true : false;
//If copy was correct then add to the database
if ($result) {
$sql = "UPDATE $TBL_QUESTIONS SET picture='".Database::escape_string(
@ -755,7 +761,7 @@ abstract class Question
{
global $picturePath;
$PictureName = explode('.', $PictureName);
$Extension = $PictureName[sizeof($PictureName) - 1];
$Extension = $PictureName[sizeof($PictureName) - 1];
// saves the picture into a temporary file
@move_uploaded_file($Picture, $picturePath.'/tmp.'.$Extension);
@ -816,18 +822,18 @@ abstract class Question
function save($exerciseId = 0)
{
$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$id = $this->id;
$question = $this->question;
$description = $this->description;
$weighting = $this->weighting;
$position = $this->position;
$type = $this->type;
$picture = $this->picture;
$level = $this->level;
$extra = $this->extra;
$c_id = $this->course['real_id'];
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$id = $this->id;
$question = $this->question;
$description = $this->description;
$weighting = $this->weighting;
$position = $this->position;
$type = $this->type;
$picture = $this->picture;
$level = $this->level;
$extra = $this->extra;
$c_id = $this->course['real_id'];
$category_list = $this->category_list;
// Question already exists
@ -857,16 +863,16 @@ abstract class Question
}
} else {
// Creates a new question
$sql = "SELECT max(position) FROM $TBL_QUESTIONS as question, $TBL_EXERCICE_QUESTION as test_question
$sql = "SELECT max(position) FROM $TBL_QUESTIONS as question, $TBL_EXERCICE_QUESTION as test_question
WHERE question.id = test_question.question_id AND
test_question.exercice_id = '".Database::escape_string($exerciseId)."' AND
question.c_id = $c_id AND
test_question.c_id = $c_id ";
$result = Database::query($sql);
$result = Database::query($sql);
$current_position = Database::result($result, 0, 0);
$this->updatePosition($current_position + 1);
$position = $this->position;
$sql = "INSERT INTO $TBL_QUESTIONS (c_id, question, description, ponderation, position, type, picture, extra, level, parent_id) VALUES ( ".
$sql = "INSERT INTO $TBL_QUESTIONS (c_id, question, description, ponderation, position, type, picture, extra, level, parent_id) VALUES ( ".
" $c_id, ".
" '".Database::escape_string($question)."', ".
" '".Database::escape_string($description)."', ".
@ -887,15 +893,19 @@ abstract class Question
// If hotspot, create first answer
if ($type == HOT_SPOT || $type == HOT_SPOT_ORDER) {
$TBL_ANSWERS = Database::get_course_table(TABLE_QUIZ_ANSWER);
$sql = "INSERT INTO $TBL_ANSWERS (c_id, question_id , answer , correct , comment , ponderation , position , hotspot_coordinates , hotspot_type )
VALUES (".$c_id.", '".Database::escape_string($this->id)."', '', NULL , '', '10' , '1', '0;0|0|0', 'square')";
$sql = "INSERT INTO $TBL_ANSWERS (c_id, question_id , answer , correct , comment , ponderation , position , hotspot_coordinates , hotspot_type )
VALUES (".$c_id.", '".Database::escape_string(
$this->id
)."', '', NULL , '', '10' , '1', '0;0|0|0', 'square')";
Database::query($sql);
}
if ($type == HOT_SPOT_DELINEATION) {
$TBL_ANSWERS = Database::get_course_table(TABLE_QUIZ_ANSWER);
$sql = "INSERT INTO $TBL_ANSWERS (c_id, question_id , answer , correct , comment , ponderation , position , hotspot_coordinates , hotspot_type )
VALUES (".$c_id.", '".Database::escape_string($this->id)."', '', NULL , '', '10' , '1', '0;0|0|0', 'delineation')";
$sql = "INSERT INTO $TBL_ANSWERS (c_id, question_id , answer , correct , comment , ponderation , position , hotspot_coordinates , hotspot_type )
VALUES (".$c_id.", '".Database::escape_string(
$this->id
)."', '', NULL , '', '10' , '1', '0;0|0|0', 'delineation')";
Database::query($sql);
}
@ -979,15 +989,15 @@ abstract class Question
$ic_slide->addValue("title", $this->question);
$ic_slide->addCourseId($course_id);
$ic_slide->addToolId(TOOL_QUIZ);
$xapian_data = array(
$xapian_data = array(
SE_COURSE_ID => $course_id,
SE_TOOL_ID => TOOL_QUIZ,
SE_DATA => array(
'type' => SE_DOCTYPE_EXERCISE_QUESTION,
SE_TOOL_ID => TOOL_QUIZ,
SE_DATA => array(
'type' => SE_DOCTYPE_EXERCISE_QUESTION,
'exercise_ids' => $question_exercises,
'question_id' => (int)$this->id
'question_id' => (int)$this->id
),
SE_USER => (int)api_get_user_id(),
SE_USER => (int)api_get_user_id(),
);
$ic_slide->xapian_data = serialize($xapian_data);
$ic_slide->addValue("content", $this->description);
@ -1050,11 +1060,11 @@ abstract class Question
function addToList($exerciseId, $fromSave = false)
{
$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$id = $this->id;
$id = $this->id;
// checks if the exercise ID is not in the list
if (!in_array($exerciseId, $this->exerciseList)) {
$this->exerciseList[] = $exerciseId;
$new_exercise = new Exercise();
$new_exercise = new Exercise();
$new_exercise->read($exerciseId);
$count = $new_exercise->selectNbrQuestions();
$count++;
@ -1132,9 +1142,9 @@ abstract class Question
{
$course_id = api_get_course_int_id();
$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER);
$TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER);
$TBL_QUIZ_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
$id = $this->id;
@ -1208,16 +1218,16 @@ abstract class Question
} else {
$course_info = $course_info;
}
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
$TBL_QUESTION_OPTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
$question = $this->question;
$question = $this->question;
$description = $this->description;
$weighting = $this->weighting;
$position = $this->position;
$type = $this->type;
$level = intval($this->level);
$extra = $this->extra;
$weighting = $this->weighting;
$position = $this->position;
$type = $this->type;
$level = intval($this->level);
$extra = $this->extra;
//Using the same method used in the course copy to transform URLs
@ -1227,7 +1237,7 @@ abstract class Question
$this->course['id'],
$course_info['id']
);
$question = DocumentManager::replace_urls_inside_content_html_from_copy_course(
$question = DocumentManager::replace_urls_inside_content_html_from_copy_course(
$question,
$this->course['id'],
$course_info['id']
@ -1240,16 +1250,16 @@ abstract class Question
$options = self::readQuestionOption($this->id, $this->course['real_id']);
//Inserting in the new course db / or the same course db
$params = array(
'c_id' => $course_id,
'question' => $question,
$params = array(
'c_id' => $course_id,
'question' => $question,
'description' => $description,
'ponderation' => $this->weighting,
'position' => $this->position,
'type' => $this->type,
'level' => $this->level,
'extra' => $this->extra,
'parent_id' => $this->parent_id,
'position' => $this->position,
'type' => $this->type,
'level' => $this->level,
'extra' => $this->extra,
'parent_id' => $this->parent_id,
);
$new_question_id = Database::insert($TBL_QUESTIONS, $params);
@ -1257,7 +1267,7 @@ abstract class Question
//Saving the quiz_options
foreach ($options as $item) {
$item['question_id'] = $new_question_id;
$item['c_id'] = $course_id;
$item['c_id'] = $course_id;
unset($item['iid']);
Database::insert($TBL_QUESTION_OPTIONS, $item);
}
@ -1270,20 +1280,24 @@ abstract class Question
return $new_question_id;
}
function get_categories_from_question() {
function get_categories_from_question()
{
return Testcategory::getCategoryForQuestion($this->id);
}
function duplicate_category_question($question_id, $course_id) {
$question = Question::read($question_id, $course_id);
function duplicate_category_question($question_id, $course_id)
{
$question = Question::read($question_id, $course_id);
$categories = $this->get_categories_from_question();
if (!empty($categories)) {
$question->saveCategories($categories);
}
}
function get_question_type_name() {
function get_question_type_name()
{
$key = self::$questionTypes[$this->type];
return get_lang($key[1]);
}
@ -1333,7 +1347,8 @@ abstract class Question
* A subclass can redifine this function to add fields...
* @param FormValidator $form the formvalidator instance (by reference)
*/
function createForm(& $form, $fck_config = 0) {
function createForm(& $form, $fck_config = 0)
{
$url = api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?1=1';
echo ' < style >
.media { display:none;}
@ -1497,7 +1512,13 @@ abstract class Question
echo '< script > $ ( function ( ) { '.$trigger.' } ) ; < / script > ';
}
$form->addElement('select', 'questionCategory', get_lang('Category'), array(), array('id' => 'category_id'));
$form->addElement(
'select',
'questionCategory',
get_lang('Category'),
array(),
array('id' => 'category_id')
);
// Categories
//$tabCat = Testcategory::getCategoriesIdAndName();
@ -1537,12 +1558,12 @@ abstract class Question
// default values
$defaults = array();
$defaults['questionName'] = $this->question;
$defaults = array();
$defaults['questionName'] = $this->question;
$defaults['questionDescription'] = $this->description;
$defaults['questionLevel'] = $this->level;
$defaults['questionCategory'] = $this->category_list;
$defaults['parent_id'] = $this->parent_id;
$defaults['questionLevel'] = $this->level;
$defaults['questionCategory'] = $this->category_list;
$defaults['parent_id'] = $this->parent_id;
//Came from he question pool
if (isset($_GET['fromExercise'])) {
@ -1601,7 +1622,7 @@ abstract class Question
static function display_type_menu($objExercise)
{
$feedback_type = $objExercise->feedback_type;
$exerciseId = $objExercise->id;
$exerciseId = $objExercise->id;
// 1. by default we show all the question types
$question_type_custom_list = self::get_question_type_list();
@ -1612,7 +1633,7 @@ abstract class Question
if ($feedback_type == 1) {
//2. but if it is a feedback DIRECT we only show the UNIQUE_ANSWER type that is currently available
$question_type_custom_list = array(
UNIQUE_ANSWER => self::$questionTypes[UNIQUE_ANSWER],
UNIQUE_ANSWER => self::$questionTypes[UNIQUE_ANSWER],
HOT_SPOT_DELINEATION => self::$questionTypes[HOT_SPOT_DELINEATION]
);
} else {
@ -1636,7 +1657,13 @@ abstract class Question
$img = $img['filename'].'_na.'.$img['extension'];
echo Display::return_icon($img, $explanation, array(), ICON_SIZE_BIG);
} else {
echo '< a href = "admin.php?'.api_get_cidreq().'&newQuestion=yes&answerType='.$i.'&exerciseId='.$exerciseId.'" > '.Display::return_icon($img, $explanation, array(), ICON_SIZE_BIG).'< / a > ';
echo '< a href = "admin.php?'.api_get_cidreq(
).'& newQuestion=yes& answerType='.$i.'& exerciseId='.$exerciseId.'">'.Display::return_icon(
$img,
$explanation,
array(),
ICON_SIZE_BIG
).'< / a > ';
}
echo '< / div > ';
echo '< / li > ';
@ -1663,10 +1690,10 @@ abstract class Question
static function saveQuestionOption($question_id, $name, $course_id, $position = 0)
{
$TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
$params['question_id'] = intval($question_id);
$params['name'] = $name;
$params['position'] = $position;
$params['c_id'] = $course_id;
$params['question_id'] = intval($question_id);
$params['name'] = $name;
$params['position'] = $position;
$params['c_id'] = $course_id;
//$result = self::readQuestionOption($question_id, $course_id);
$last_id = Database::insert($TBL_EXERCICE_QUESTION_OPTION, $params);
@ -1685,7 +1712,7 @@ abstract class Question
static function updateQuestionOption($id, $params, $course_id)
{
$TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
$result = Database::update(
$result = Database::update(
$TBL_EXERCICE_QUESTION_OPTION,
$params,
array('c_id = ? AND id = ?' => array($course_id, $id))
@ -1694,16 +1721,26 @@ abstract class Question
return $result;
}
static function readQuestionOption($question_id, $course_id) {
static function readQuestionOption($question_id, $course_id)
{
$TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION);
$result = Database::select('*', $TBL_EXERCICE_QUESTION_OPTION, array('where' => array('c_id = ? AND question_id = ?' => array($course_id, $question_id)), 'order' => 'iid ASC'));
$result = Database::select(
'*',
$TBL_EXERCICE_QUESTION_OPTION,
array(
'where' => array('c_id = ? AND question_id = ?' => array($course_id, $question_id)),
'order' => 'iid ASC'
)
);
if (!empty($result)) {
$new_result = array();
foreach ($result as $item) {
$new_result[$item['iid']] = $item;
}
return $new_result;
}
return array();
}
@ -1723,19 +1760,19 @@ abstract class Question
$counter_label = intval($counter);
}
$score_label = get_lang('Wrong');
$class = 'error';
$class = 'error';
if ($score['pass'] == true) {
$score_label = get_lang('Correct');
$class = 'success';
$class = 'success';
}
if ($this->type == FREE_ANSWER || $this->type == ORAL_EXPRESSION) {
if ($score['revised'] == true) {
$score_label = get_lang('Revised');
$class = '';
$class = '';
} else {
$score_label = get_lang('NotRevised');
$class = 'error';
$class = 'error';
}
}
$question_title = $this->question;
@ -1747,7 +1784,10 @@ abstract class Question
}
$header .= Display::page_subheader2($counter_label.". ".$question_title);
//$header .= Display::div('< div class = "rib rib-'.$class.'" > < h3 > '.$score_label.'< / h3 > < / div > < h4 > '.($score['result']).' < / h4 > < h5 class = "'.$class.'" > '.$score['result'].' < / h5 > ', array('class'=>'ribbon'));
$header .= Display::div('< div class = "rib rib-'.$class.'" > < h3 > '.$score_label.'< / h3 > < / div > < h4 > '.$score['result'].' < / h4 > ', array('class' => 'ribbon'));
$header .= Display::div(
'< div class = "rib rib-'.$class.'" > < h3 > '.$score_label.'< / h3 > < / div > < h4 > '.$score['result'].' < / h4 > ',
array('class' => 'ribbon')
);
$header .= Display::div($this->description, array('id' => 'question_description'));
return $header;
@ -1765,36 +1805,38 @@ abstract class Question
{
$course_id = api_get_course_int_id();
$tbl_quiz_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
$tbl_quiz_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
$tbl_quiz_rel_question = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$quiz_id = intval($quiz_id);
$quiz_id = intval($quiz_id);
$max_score = (float)$max_score;
$type = intval($type);
$level = intval($level);
$type = intval($type);
$level = intval($level);
// Get the max position
$sql = "SELECT max(position) as max_position"
$sql = "SELECT max(position) as max_position"
." FROM $tbl_quiz_question q INNER JOIN $tbl_quiz_rel_question r"
." ON q.iid = r.question_id"
." AND exercice_id = $quiz_id AND q.c_id = $course_id AND r.c_id = $course_id";
$rs_max = Database::query($sql);
$row_max = Database::fetch_object($rs_max);
$rs_max = Database::query($sql);
$row_max = Database::fetch_object($rs_max);
$max_position = $row_max->max_position + 1;
// Insert the new question
$sql = "INSERT INTO $tbl_quiz_question (c_id, question, ponderation, position, type, level)
VALUES ($course_id, '".Database::escape_string($question_name)."', '$max_score', $max_position, $type, $level)";
VALUES ($course_id, '".Database::escape_string(
$question_name
)."', '$max_score', $max_position, $type, $level)";
Database::query($sql);
// Get the question ID
$question_id = Database::get_last_insert_id();
// Get the max question_order
$sql = "SELECT max(question_order) as max_order "
$sql = "SELECT max(question_order) as max_order "
."FROM $tbl_quiz_rel_question WHERE c_id = $course_id AND exercice_id = $quiz_id ";
$rs_max_order = Database::query($sql);
$rs_max_order = Database::query($sql);
$row_max_order = Database::fetch_object($rs_max_order);
$max_order = $row_max_order->max_order + 1;
$max_order = $row_max_order->max_order + 1;
// Attach questions to quiz
$sql = "INSERT INTO $tbl_quiz_rel_question (c_id, question_id, exercice_id, question_order)"
." VALUES($course_id, $question_id, $quiz_id, $max_order)";
@ -1832,7 +1874,7 @@ abstract class Question
$where_condition = array()
) {
$table_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
$default_where = array('c_id = ? AND parent_id = 0 AND type = ?' => array($course_id, MEDIA_QUESTION));
$default_where = array('c_id = ? AND parent_id = 0 AND type = ?' => array($course_id, MEDIA_QUESTION));
if (!empty($where_condition)) {
//$where_condition
}
@ -1856,7 +1898,7 @@ abstract class Question
static function get_count_course_medias($course_id)
{
$table_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
$result = Database::select(
$result = Database::select(
'count(*) as count',
$table_question,
array('where' => array('c_id = ? AND parent_id = 0 AND type = ?' => array($course_id, MEDIA_QUESTION))),
@ -1872,8 +1914,8 @@ abstract class Question
static function prepare_course_media_select($course_id)
{
$medias = self::get_course_medias($course_id);
$media_list = array();
$medias = self::get_course_medias($course_id);
$media_list = array();
$media_list[0] = get_lang('NoMedia');
if (!empty($medias)) {
@ -1903,7 +1945,7 @@ abstract class Question
$html = null;
if ($this->parent_id != 0) {
$parent_question = Question::read($this->parent_id);
$html = $parent_question->show_media_content();
$html = $parent_question->show_media_content();
} else {
$html .= Display::page_subheader($this->selectTitle());
$html .= $this->selectDescription();
@ -1912,9 +1954,12 @@ abstract class Question
return $html;
}
static function question_type_no_review() {
static function question_type_no_review()
{
return array(
HOT_SPOT, HOT_SPOT_ORDER, HOT_SPOT_DELINEATION
HOT_SPOT,
HOT_SPOT_ORDER,
HOT_SPOT_DELINEATION
);
}
}