diff --git a/main/exercice/admin.php b/main/exercice/admin.php index c0f73d9cb4..275e7a9a5b 100644 --- a/main/exercice/admin.php +++ b/main/exercice/admin.php @@ -42,6 +42,7 @@ * * @package chamilo.exercise * @author Olivier Brouckaert +* Modified by Hubert Borderiou 21-10-2011 Question by category */ /** * Code @@ -234,7 +235,6 @@ if ($cancelQuestion) { } else { // goes back to the question viewing $editQuestion=$modifyQuestion; - unset($newQuestion,$modifyQuestion); } } @@ -448,6 +448,9 @@ if (isset($exerciseId) && !empty($exerciseId)) { } } +// If we are in a test +$inATest = isset($exerciseId) && $exerciseId > 0; +if ($inATest) { echo '
'; if (isset($_GET['hotspotadmin']) || isset($_GET['newQuestion']) || isset($_GET['myid'])) echo ''.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').''; @@ -473,20 +476,33 @@ foreach ($objExercise->questionList as $q) { echo ''.sprintf(get_lang('XQuestionsWithTotalScoreY'),$objExercise->selectNbrQuestions(),$maxScoreAllQuestions).''; echo '
'; +} +else if (isset($_GET['newQuestion'])) { + // we are in create a new question from question pool not in a test + echo '
'; + echo '.'.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').''; + echo '
'; +} +else { + // If we are in question_poolbut not in an test, go back to question create in pool + echo '
'; + echo ''.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').''; + echo '
'; + +} if (isset($_GET['message'])) { if (in_array($_GET['message'], array('ExerciseStored', 'ItemUpdated', 'ItemAdded'))) { Display::display_confirmation_message(get_lang($_GET['message'])); } } - if ($newQuestion || $editQuestion) { // statement management $type = Security::remove_XSS($_REQUEST['answerType']); echo ''; require 'question_admin.inc.php'; } - + if (isset($_GET['hotspotadmin'])) { if (!is_object($objQuestion)) { $objQuestion = Question :: read($_GET['hotspotadmin']); @@ -495,6 +511,7 @@ if (isset($_GET['hotspotadmin'])) { api_not_allowed(); } require 'hotspot_admin.inc.php';} + if (!$newQuestion && !$modifyQuestion && !$editQuestion && !isset($_GET['hotspotadmin'])) { // question list management require 'question_list_admin.inc.php'; @@ -503,5 +520,4 @@ if (!$newQuestion && !$modifyQuestion && !$editQuestion && !isset($_GET['hotspot api_session_register('objExercise'); api_session_register('objQuestion'); api_session_register('objAnswer'); - Display::display_footer(); diff --git a/main/exercice/exercice.php b/main/exercice/exercice.php index 8283fe6fac..17744f0141 100644 --- a/main/exercice/exercice.php +++ b/main/exercice/exercice.php @@ -7,6 +7,7 @@ * @author Denes Nagy, HotPotatoes integration * @author Wolfgang Schneider, code/html cleanup * @author Julio Montoya , lots of cleanup + several improvements +* Modified by hubert.borderiou (question category) */ /** * Code @@ -197,8 +198,7 @@ if ($show == 'result' && $_REQUEST['comments'] == 'update' && ($is_allowedToEdit Database::query($query); //Saving results in the track recording table - $recording_changes = 'INSERT INTO '.$TBL_TRACK_ATTEMPT_RECORDING.' (exe_id, question_id, marks, insert_date, author, teacher_comment) - VALUES ('."'$id','".$my_questionid."','$my_marks','".api_get_utc_datetime()."','".api_get_user_id()."'".',"'.$my_comments.'")'; + $recording_changes = 'INSERT INTO '.$TBL_TRACK_ATTEMPT_RECORDING.' (exe_id, question_id, marks, insert_date, author, teacher_comment) VALUES ('."'$id','".$my_questionid."','$my_marks','".api_get_utc_datetime()."','".api_get_user_id()."'".',"'.$my_comments.'")'; Database::query($recording_changes); } @@ -520,6 +520,14 @@ if ($is_allowedToEdit && $origin != 'learnpath') { if ($show != 'result') { echo '' . Display :: return_icon('new_exercice.png', get_lang('NewEx'),'','32').''; echo '' . Display :: return_icon('new_question.png', get_lang('AddQ'),'','32').''; + // Question category + echo ''; + echo Display::return_icon('question_category.gif', get_lang('QuestionCategory')); + echo ''; + echo ''; + echo Display::return_icon('database.png', get_lang('langQuestionPool'), array('style'=>'width:32px')); + echo ''; + // end question category echo '' . Display :: return_icon('import_hotpotatoes.png', get_lang('ImportHotPotatoesQuiz'),'','32').''; // link to import qti2 ... echo '' . Display :: return_icon('import_qti2.png', get_lang('ImportQtiQuiz'),'','32') .''; diff --git a/main/exercice/exercise.class.php b/main/exercice/exercise.class.php index e013fbc62b..95b9f36aff 100644 --- a/main/exercice/exercise.class.php +++ b/main/exercice/exercise.class.php @@ -5,6 +5,7 @@ * @package chamilo.exercise * @author Olivier Brouckaert * @author Julio Montoya Cleaning exercises + * Modified by Hubert Borderiou 2011-10-21 (question category) */ /** * Code @@ -48,6 +49,7 @@ class Exercise { public $course; public $propagate_neg; public $review_answers; // + public $randomByCat; /** @@ -72,6 +74,7 @@ class Exercise { $this->expired_time = '0000-00-00 00:00:00'; $this->propagate_neg = 0; $this->review_answers = false; + $this->randomByCat = 0; // if (!empty($course_id)) { $course_info = api_get_course_info_by_id($this->course_id); @@ -114,6 +117,7 @@ class Exercise { $this->attempts = $object->max_attempt; $this->feedbacktype = $object->feedback_type; $this->propagate_neg = $object->propagate_neg; + $this->randomByCat = $object->random_by_category; // $this->review_answers = (isset($object->review_answers) && $object->review_answers == 1) ? true : false; @@ -234,6 +238,53 @@ class Exercise { return $this->type; } + + /** + * return 1 or 2 if randomByCat + * @author - hubert borderiou + * @return - integer - quiz random by category + */ + function selectRandomByCat() { + return $this->randomByCat; + } + + /** + * return 0 if no random by cat + * return 1 if rendom by cat, categories shuffled + * return 2 if random by cat, categories sorted by alphabetic order + * @author - hubert borderiou + * @return - integer - quiz random by category + */ + function isRandomByCat() { + $res = 0; + if ($this->randomByCat == 1) { + $res = 1; + } + else if ($this->randomByCat == 2) { + $res = 2; + } + return $res; + } + + /** + * return nothing + * update randomByCat value for object + * @author - hubert borderiou + */ + function updateRandomByCat($in_randombycat) { + if ($in_randombycat == 1) { + $this->randomByCat = 1; + } + else if ($in_randombycat == 2) { + $this->randomByCat = 2; + } + else { + $this->randomByCat = 0; + } + } + + + /** * tells if questions are selected randomly, and if so returns the draws * @@ -554,6 +605,7 @@ class Exercise { $active = $this->active; $propagate_neg = $this->propagate_neg; $review_answers = (isset($this->review_answers) && $this->review_answers) ? 1 : 0; + $randomByCat = $this->randomByCat; // $session_id = api_get_session_id(); @@ -584,9 +636,10 @@ class Exercise { start_time = '$start_time', end_time = '$end_time', max_attempt ='".Database::escape_string($attempts)."', - expired_time ='".Database::escape_string($expired_time)."', - propagate_neg ='".Database::escape_string($propagate_neg)."', - review_answers ='".Database::escape_string($review_answers)."', + expired_time ='".Database::escape_string($expired_time)."', + propagate_neg ='".Database::escape_string($propagate_neg)."', + review_answers ='".Database::escape_string($review_answers)."', + random_by_category ='".Database::escape_string($randomByCat)."', results_disabled='".Database::escape_string($results_disabled)."'"; } @@ -601,8 +654,7 @@ class Exercise { } } else { // creates a new exercise - $sql="INSERT INTO $TBL_EXERCICES (c_id, start_time, end_time, title, description, sound, type, random, random_answers, - active, results_disabled, max_attempt, feedback_type, expired_time, session_id, review_answers) + $sql="INSERT INTO $TBL_EXERCICES (c_id, start_time, end_time, title, description, sound, type, random, random_answers, active, results_disabled, max_attempt, feedback_type, expired_time, session_id, review_answers, random_by_category) VALUES( ".$this->course_id.", '$start_time','$end_time', @@ -618,7 +670,8 @@ class Exercise { '".Database::escape_string($feedbacktype)."', '".Database::escape_string($expired_time)."', '".Database::escape_string($session_id)."', - '".Database::escape_string($review_answers)."' + '".Database::escape_string($review_answers)."', + '".Database::escape_string($randomByCat)."' )"; Database::query($sql); $this->id = Database::insert_id(); @@ -868,6 +921,15 @@ class Exercise { $radios_random_answers[] = FormValidator :: createElement ('radio', 'randomAnswers', null, get_lang('No'),'0'); $form->addGroup($radios_random_answers, null, get_lang('RandomAnswers')); + //randow by category + $form->addElement('html','
 
'); + $radiocat = array(); + $radiocat[] = FormValidator::createElement('radio', 'randomByCat', null, get_lang('yesWithCategoriesShuffled'),'1'); + $radiocat[] = FormValidator::createElement('radio', 'randomByCat', null, get_lang('yesWithCategoriesSorted'),'2'); + $radiocat[] = FormValidator::createElement('radio', 'randomByCat', null, get_lang('No'),'0'); + $form->addGroup($radiocat, null, get_lang('RandomQuestionByCategory')); + $form->addElement('html','
 
'); + //Attempts $attempt_option=range(0,10); $attempt_option[0]=get_lang('Infinite'); @@ -898,6 +960,7 @@ class Exercise { //$check_option=$this->selectType(); $diplay = 'block'; $form->addElement('checkbox', 'propagate_neg', get_lang('PropagateNegativeResults'), null); + $form->addElement('html','
 
'); $form->addElement('checkbox', 'review_answers', get_lang('ReviewAnswers'), null); $form->addElement('html','
'); @@ -981,9 +1044,8 @@ class Exercise { $defaults['exerciseFeedbackType'] = $this->selectFeedbackType(); $defaults['results_disabled'] = $this->selectResultsDisabled(); $defaults['propagate_neg'] = $this->selectPropagateNeg(); - $defaults['review_answers'] = $this->review_answers; - + $defaults['randomByCat'] = $this->selectRandomByCat(); // if (($this->start_time!='0000-00-00 00:00:00')) $defaults['activate_start_date_check'] = 1; @@ -1008,7 +1070,7 @@ class Exercise { $defaults['exerciseDescription'] = ''; $defaults['exerciseFeedbackType'] = 0; $defaults['results_disabled'] = 0; - + $defaults['randomByCat'] = 0; // $defaults['start_time'] = date('Y-m-d 12:00:00'); $defaults['end_time'] = date('Y-m-d 12:00:00',time()+84600); } @@ -1038,7 +1100,7 @@ class Exercise { $this->updateResultsDisabled($form->getSubmitValue('results_disabled')); $this->updateExpiredTime($form->getSubmitValue('enabletimercontroltotalminutes')); $this->updatePropagateNegative($form->getSubmitValue('propagate_neg')); - + $this->updateRandomByCat($form->getSubmitValue('randomByCat')); // $this->updateReviewAnswers($form->getSubmitValue('review_answers')); if ($form->getSubmitValue('activate_start_date_check') == 1) { @@ -3223,8 +3285,62 @@ class Exercise { } function get_validated_question_list() { - return ($this->isRandom() ? $this->selectRandomList() : $this->selectQuestionList()); - } + $tabres = array(); + $isRandomByCategory = $this->isRandomByCat(); + if (!$isRandomByCategory) { + if ($this->isRandom()) { + $tabres = $this->selectRandomList(); + } + else { + $tabres = $this->selectQuestionList(); + } + } + else { + if ($this->isRandom()) { + if (!class_exists("Testcategory")) { + require_once("testcategory.class.php"); + } + // ----------------------------- + // USE question categories hub 13-10-2011 + // ----------------------------- + // get questions by category for this exercice + // we have to choice $objExercise->random question in each array values of $tabCategoryQuestions + // key of $tabCategoryQuestions are the categopy id (0 for not in a category) + // value is the array of question id of this category + $questionList = array(); + $tabCategoryQuestions = array(); + $tabCategoryQuestions = Testcategory::getQuestionsByCat($this->id); + $isRandomByCategory = $this->selectRandomByCat(); + // on tri les catégories en fonction du terme entre [] en tête de la description de la catégorie + /* + * ex de catégories : + * [biologie] Maîtriser les mécanismes de base de la génétique + * [biologie] Relier les moyens de défenses et les agents infectieux + * [biologie] Savoir où est produite l'énergie dans les cellules et sous quelle forme + * [chimie] Classer les molécules suivant leur pouvoir oxydant ou réducteur + * [chimie] Connaître la définition de la théorie acide/base selon Brönsted + * [chimie] Connaître les charges des particules + * On veut dans l'ordre des groupes définis par le terme entre crochet au début du titre de la catégorie + */ + // If test option is Grouped By Categories + if ($isRandomByCategory == 2) { + $tabCategoryQuestions = Testcategory::sortTabByBracketLabel($tabCategoryQuestions); // 24-02-2011 hub pour projet Bernard Ycard + } + while (list($cat_id, $tabquestion) = each($tabCategoryQuestions)) { + $questionList = array_merge($questionList, Testcategory::getNElementsFromArray($tabquestion, $this->random)); + } + // shuffle the question list if test is not grouped by categories + if ($isRandomByCategory == 1) { + shuffle($questionList); // or not + } + $tabres = $questionList; + } + else { + // Problem, random by category has been selected and we have no $this->isRandom nnumber of question selected + // Should not happened + } + } + return $tabres; } public function get_stat_track_exercise_info_by_exe_id($exe_id) { $track_exercises = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES); diff --git a/main/exercice/exercise.lib.php b/main/exercice/exercise.lib.php index 9dc7a81a59..6bd467c29e 100644 --- a/main/exercice/exercise.lib.php +++ b/main/exercice/exercise.lib.php @@ -8,6 +8,7 @@ * @package chamilo.exercise * @author Olivier Brouckaert * @version $Id: exercise.lib.php 22247 2009-07-20 15:57:25Z ivantcholakov $ + * Modified by Hubert Borderiou 2011-10-21 Question Category */ /** * Code @@ -51,6 +52,7 @@ function showQuestion($questionId, $only_questions = false, $origin = false, $cu $questionDescription = $objQuestionTmp->selectDescription(); if ($show_title) { + Testcategory::displayCategoryAndTitle($objQuestionTmp->id); // echo Display::div($current_item.'. '.$objQuestionTmp->selectTitle(), array('class'=>'question_title')); } if (!empty($questionDescription)) { @@ -501,6 +503,7 @@ function showQuestion($questionId, $only_questions = false, $origin = false, $cu if (!$only_questions) { if ($show_title) { + Testcategory::displayCategoryAndTitle($objQuestionTmp->id); // echo '
'.$current_item.'. '.$questionName.'
'; } //@todo I need to the get the feedback type @@ -1257,6 +1260,29 @@ function get_all_exercises($course_info = null, $session_id = 0, $check_dates = return Database::select('*',$TBL_EXERCICES, $conditions); } + +/** + * Getting all active exercises from a course from a session (if a session_id is provided we will show all the exercises in the course + all exercises in the session) + * @param array course data + * @param int session id + * @param int course c_id + * @return array array with exercise data + * modified by Hubert Borderiou + */ +function get_all_exercises_for_course_id($course_info = null, $session_id = 0, $course_id=0) { + $TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST); + if ($session_id == -1) { + $session_id = 0; + } + if ($session_id == 0) { + $conditions = array('where'=>array('active = ? AND session_id = ? AND c_id=?'=>array('1', $session_id, $course_id)), 'order'=>'title'); + } else { + //All exercises + $conditions = array('where'=>array('active = ? AND (session_id = 0 OR session_id = ? ) AND c_id=?' =>array('1', $session_id, $course_id)), 'order'=>'title'); + } + return Database::select('*',$TBL_EXERCICES, $conditions); +} + /** * Gets the position of the score based in a given score (result/weight) and the exe_id based in the user list * (NO Exercises in LPs ) diff --git a/main/exercice/exercise_submit.php b/main/exercice/exercise_submit.php index e1a27fe07a..69b899d13f 100644 --- a/main/exercice/exercise_submit.php +++ b/main/exercice/exercise_submit.php @@ -22,6 +22,7 @@ * Cleaning exercises (2010), * Adding hotspot delineation support (2011) * Adding reminder + ajax support (2011) +* Modified by hubert.borderiou (2011-10-21 question category) */ /** * Code @@ -585,6 +586,10 @@ if ($question_count != 0) { } } else { $error = get_lang('ThereAreNoQuestionsForThisExercise'); + // if we are in the case where user select random by category, but didn't choose the number of random question + if ($objExercise->selectRandomByCat() > 0 && $objExercise->random <= 0) { + $error .= "
".get_lang('pleaseSelectSomeRandomQuestion'); + } } if (!empty ($_GET['gradebook']) && $_GET['gradebook'] == 'view') { diff --git a/main/exercice/question.class.php b/main/exercice/question.class.php index fabf10361f..ce13dbd0a0 100644 --- a/main/exercice/question.class.php +++ b/main/exercice/question.class.php @@ -5,10 +5,12 @@ * @package chamilo.exercise * @author Olivier Brouckaert * @author Julio Montoya lot of bug fixes +* Modified by hubert.borderiou@grenet.fr - add question categories */ /** * Code */ + if(!class_exists('Question')): // answer types @@ -25,6 +27,7 @@ define('UNIQUE_ANSWER_NO_OPTION', 10); define('MULTIPLE_ANSWER_TRUE_FALSE', 11); define('MULTIPLE_ANSWER_COMBINATION_TRUE_FALSE', 12); +if (!class_exists('Category')) include_once("testcategory.class.php"); // hub 12-10-2011 /** QUESTION CLASS @@ -46,8 +49,9 @@ abstract class Question public $level; public $picture; public $exerciseList; // array with the list of exercises which this question is in + public $category; // hub 12-10-2011 private $isContent; - public $course; + public $course; static $typePicture = 'new_question.png'; static $explanationLangVar = ''; @@ -79,10 +83,10 @@ abstract class Question $this->position=1; $this->picture=''; $this->level = 1; - $this->extra=''; + $this->category=0; // hub 12-10-2011 + $this->extra=''; $this->exerciseList=array(); $this->course = api_get_course_info(); - $this->course_id = api_get_course_int_id(); } public function getIsContent() { @@ -105,17 +109,17 @@ abstract class Question if (!empty($course_id)) { $course_info = api_get_course_info_by_id($course_id); - } else { + } else { + global $course; $course_info = api_get_course_info(); } $course_id = $course_info['real_id']; - $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST); - $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); - $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); + $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST, $course_info['db_name']); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION, $course_info['db_name']); + $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION, $course_info['db_name']); - $sql = "SELECT question,description,ponderation,position,type,picture,level,extra - FROM $TBL_QUESTIONS WHERE c_id = $course_id AND id = $id "; + $sql = "SELECT question,description,ponderation,position,type,picture,level,extra FROM $TBL_QUESTIONS WHERE c_id = $course_id AND id = $id "; $result = Database::query($sql); @@ -132,8 +136,9 @@ abstract class Question $objQuestion->type = $object->type; $objQuestion->picture = $object->picture; $objQuestion->level = (int) $object->level; - $objQuestion->extra = $object->extra; - $objQuestion->course = $course_info; + $objQuestion->extra = $object->extra; + $objQuestion->course = $course_info; + $objQuestion->category = Testcategory::getCategoryForQuestion($id); // hub 12-10-2011 $sql = "SELECT exercice_id FROM $TBL_EXERCICE_QUESTION WHERE c_id = $course_id AND question_id = $id"; $result_exercise_list = Database::query($sql); @@ -299,6 +304,74 @@ abstract class Question $this->weighting=$weighting; } + + /** + * @author - Hubert Borderiou 12-10-2011 + * @param - array of category $in_category + */ + function updateCategory($in_category) { + $this->category=$in_category; + } + + /** + * @author - Hubert Borderiou 12-10-2011 + * @param - interger $in_positive + */ + function updateScoreAlwaysPositive($in_positive) { + $this->scoreAlwaysPositive=$in_positive; + } + + /** + * @author - Hubert Borderiou 12-10-2011 + * @param - interger $in_positive + */ + function updateUncheckedMayScore($in_positive) { + $this->uncheckedMayScore=$in_positive; + } + + /** + * @author - Hubert Borderiou 12-10-2011 + * @param - interger $in_positive + * in this version, a question can only have 1 category + * if category is 0, then question has no category then delete the category entry + */ + function saveCategory($in_category) { + if ($in_category <= 0) { + $this->deleteCategory(); + } + // update or add category for a question + else { + $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); + 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(); + $res = Database::query($sql); + } + else { + $sql = "INSERT INTO $TBL_QUESTION_REL_CATEGORY VALUES (".api_get_course_int_id().", $question_id, $category_id)"; + $res = Database::query($sql); + } + } + } + + /** + * @author hubert borderiou 12-10-2011 + * delete any category entry for question id + * @param : none + * delte the category for question + */ + function deleteCategory() { + $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=".api_get_course_int_id(); + $res = Database::query($sql); + } + + /** * changes the question position * @@ -329,16 +402,17 @@ abstract class Question * @param - integer $type - answer type */ function updateType($type) { - $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER); + $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER, $this->course['db_name']); // if we really change the type if($type != $this->type) { // if we don't change from "unique answer" to "multiple answers" (or conversely) - if(!in_array($this->type,array(UNIQUE_ANSWER, MULTIPLE_ANSWER)) || !in_array($type,array(UNIQUE_ANSWER,MULTIPLE_ANSWER))) { + if(!in_array($this->type,array(UNIQUE_ANSWER,MULTIPLE_ANSWER)) || !in_array($type,array(UNIQUE_ANSWER,MULTIPLE_ANSWER))) { // removes old answers - $sql = "DELETE FROM $TBL_REPONSES WHERE c_id = ".api_get_course_int_id()." AND question_id = ".Database::escape_string($this->id); + $sql="DELETE FROM $TBL_REPONSES WHERE question_id='".Database::escape_string($this->id)."'"; Database::query($sql); } + $this->type=$type; } } @@ -479,12 +553,12 @@ abstract class Question */ function exportPicture($questionId, $course_info) { $course_id = $course_info['real_id']; - $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION, $course_info['db_name']); $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'; // if the question has got an ID and if the picture exists - if ($this->id && !empty($this->picture)) { + if($this->id && !empty($this->picture)) { $picture=explode('.',$this->picture); $Extension=$picture[sizeof($picture)-1]; $picture='quiz-'.$questionId.'.'.$Extension; @@ -577,8 +651,8 @@ 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); + $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION, $this->course['db_name']); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION, $this->course['db_name']); $id = $this->id; $question = $this->question; @@ -588,11 +662,13 @@ abstract class Question $type = $this->type; $picture = $this->picture; $level = $this->level; - $extra = $this->extra; - $c_id = $this->course['real_id']; - + $extra = $this->extra; + $c_id = $this->course['real_id']; + $category = $this->category; // hub 12-10-2011 + + // question already exists - if (!empty($id)) { + if(!empty($id)) { $sql="UPDATE $TBL_QUESTIONS SET question ='".Database::escape_string($question)."', description ='".Database::escape_string($description)."', @@ -600,23 +676,24 @@ abstract class Question position ='".Database::escape_string($position)."', type ='".Database::escape_string($type)."', picture ='".Database::escape_string($picture)."', - extra ='".Database::escape_string($extra)."', + extra ='".Database::escape_string($extra)."', level ='".Database::escape_string($level)."' - WHERE c_id = ".$c_id." AND id = '".Database::escape_string($id)."'"; + WHERE id='".Database::escape_string($id)."'"; Database::query($sql); + $this->saveCategory($category); // hub 12-10-2011 if (!empty($exerciseId)) { api_item_property_update($this->course, TOOL_QUIZ, $id,'QuizQuestionUpdated',api_get_user_id); } - if (api_get_setting('search_enabled')=='true') { - if ($exerciseId != 0) { - $this -> search_engine_edit($exerciseId); - } else { - /** - * actually there is *not* an user interface for - * creating questions without a relation with an exercise - */ - } - } + if (api_get_setting('search_enabled')=='true') { + if ($exerciseId != 0) { + $this -> search_engine_edit($exerciseId); + } else { + /** + * actually there is *not* an user interface for + * creating questions without a relation with an exercise + */ + } + } } else { // creates a new question @@ -624,7 +701,8 @@ abstract class 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 + test_question.c_id = $c_id + "; $result = Database::query($sql); $current_position = Database::result($result,0,0); @@ -642,8 +720,9 @@ abstract class Question '".Database::escape_string($level)."' )"; Database::query($sql); + $this->id = Database::insert_id(); - + api_item_property_update($this->course, TOOL_QUIZ, $this->id,'QuizQuestionAdded',api_get_user_id()); // If hotspot, create first answer @@ -662,16 +741,17 @@ abstract class Question } - if (api_get_setting('search_enabled')=='true') { - if ($exerciseId != 0) { - $this -> search_engine_edit($exerciseId, TRUE); - } else { - /** - * actually there is *not* an user interface for - * creating questions without a relation with an exercise - */ - } - } + if (api_get_setting('search_enabled')=='true') { + if ($exerciseId != 0) { + $this -> search_engine_edit($exerciseId, TRUE); + } + else { + /** + * actually there is *not* an user interface for + * creating questions without a relation with an exercise + */ + } + } } // if the question is created in an exercise @@ -835,28 +915,28 @@ abstract class Question $id=$this->id; // searches the position of the exercise ID in the list - $pos = array_search($exerciseId,$this->exerciseList); + $pos=array_search($exerciseId,$this->exerciseList); // exercise not found - if ($pos === false) { + if($pos === false) { return false; } else { // deletes the position in the array containing the wanted exercise ID unset($this->exerciseList[$pos]); //update order of other elements - $sql = "SELECT question_order FROM $TBL_EXERCICE_QUESTION WHERE c_id = ".api_get_course_int_id()." AND question_id='".Database::escape_string($id)."' AND exercice_id='".Database::escape_string($exerciseId)."'"; + $sql = "SELECT question_order FROM $TBL_EXERCICE_QUESTION WHERE question_id='".Database::escape_string($id)."' AND exercice_id='".Database::escape_string($exerciseId)."'"; $res = Database::query($sql); if (Database::num_rows($res)>0) { $row = Database::fetch_array($res); if (!empty($row['question_order'])) { - echo $sql = "UPDATE $TBL_EXERCICE_QUESTION SET question_order = question_order-1 - WHERE c_id = ".api_get_course_int_id()." AND exercice_id='".Database::escape_string($exerciseId)."' AND question_order > ".$row['question_order']; + $sql = "UPDATE $TBL_EXERCICE_QUESTION SET question_order = question_order-1 WHERE exercice_id='".Database::escape_string($exerciseId)."' AND question_order > ".$row['question_order']; $res = Database::query($sql); } } - $sql = "DELETE FROM $TBL_EXERCICE_QUESTION WHERE c_id = ".api_get_course_int_id()." AND question_id='".Database::escape_string($id)."' AND exercice_id='".Database::escape_string($exerciseId)."'"; + $sql="DELETE FROM $TBL_EXERCICE_QUESTION WHERE question_id='".Database::escape_string($id)."' AND exercice_id='".Database::escape_string($exerciseId)."'"; Database::query($sql); + return true; } } @@ -869,45 +949,52 @@ abstract class Question * @author - Olivier Brouckaert * @param - integer $deleteFromEx - exercise ID if the question is only removed from one exercise */ - function delete($deleteFromEx = 0) { + function delete($deleteFromEx=0) { global $_course,$_user; - $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); - - $id = $this->id; + $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION, $this->course['db_name']); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION, $this->course['db_name']); + $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER, $this->course['db_name']); + $TBL_QUIZ_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY, $this->course['db_name']); // hub 12-10-2011 + + $id=$this->id; // if the question must be removed from all exercises - if (!$deleteFromEx) { + if(!$deleteFromEx) + { //update the question_order of each question to avoid inconsistencies - $sql = "SELECT exercice_id, question_order FROM $TBL_EXERCICE_QUESTION WHERE c_id = ".api_get_course_int_id()." AND question_id='".Database::escape_string($id)."'"; + $sql = "SELECT exercice_id, question_order FROM $TBL_EXERCICE_QUESTION WHERE question_id='".Database::escape_string($id)."'"; $res = Database::query($sql); if (Database::num_rows($res)>0) { while ($row = Database::fetch_array($res)) { if (!empty($row['question_order'])) { - $sql = "UPDATE $TBL_EXERCICE_QUESTION SET question_order = question_order-1 - WHERE c_id = ".api_get_course_int_id()." AND exercice_id='".Database::escape_string($row['exercice_id'])."' AND question_order > ".$row['question_order']; + $sql = "UPDATE $TBL_EXERCICE_QUESTION SET question_order = question_order-1 WHERE exercice_id='".Database::escape_string($row['exercice_id'])."' AND question_order > ".$row['question_order']; $res = Database::query($sql); } } } - $sql="DELETE FROM $TBL_EXERCICE_QUESTION WHERE c_id = ".api_get_course_int_id()." AND question_id='".Database::escape_string($id)."'"; + $sql="DELETE FROM $TBL_EXERCICE_QUESTION WHERE question_id='".Database::escape_string($id)."'"; Database::query($sql); - $sql="DELETE FROM $TBL_QUESTIONS WHERE c_id = ".api_get_course_int_id()." AND id='".Database::escape_string($id)."'"; + $sql="DELETE FROM $TBL_QUESTIONS WHERE id='".Database::escape_string($id)."'"; Database::query($sql); - $sql="DELETE FROM $TBL_REPONSES WHERE c_id = ".api_get_course_int_id()." AND question_id='".Database::escape_string($id)."'"; + $sql="DELETE FROM $TBL_REPONSES WHERE question_id='".Database::escape_string($id)."'"; Database::query($sql); + // hub 12-10-2011 remove the category of this question in the question_rel_category table + $sql = "DELETE FROM $TBL_QUIZ_QUESTION_REL_CATEGORY WHERE question_id='".Database::escape_string($id)."' AND c_id=".api_get_course_int_id(); + Database::query($sql); + api_item_property_update($this->course, TOOL_QUIZ, $id,'QuizQuestionDeleted',api_get_user_id()); $this->removePicture(); // resets the object $this->Question(); - } // just removes the exercise from the list - else { + } + // just removes the exercise from the list + else + { $this->removeFromList($deleteFromEx); if (api_get_setting('search_enabled')=='true' && extension_loaded('xapian')) { // disassociate question with this exercise @@ -931,8 +1018,8 @@ abstract class Question } else { $course_info = $course_info; } - $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); - $TBL_QUESTION_OPTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION, $course_info['db_name']); + $TBL_QUESTION_OPTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION, $course_info['db_name']); $question = $this->question; $description = $this->description; @@ -1007,7 +1094,8 @@ abstract class Question echo ''; @@ -1041,17 +1149,12 @@ abstract class Question //$test=FormValidator :: createElement ('text', 'questionName'); //$radios_results_enabled[]=$test; - // question level - //@todo move levles into a table - $select_level = array (1,2,3,4,5); - //$radios_results_enabled[] = - foreach($select_level as $val) { - $radios_results_enabled[] = FormValidator :: createElement ('radio', null, null,$val,$val); - } - $form->addGroup($radios_results_enabled,'questionLevel',get_lang('Difficulty')); $renderer->setElementTemplate('
{label}
{element}
','questionName'); $renderer->setElementTemplate('
{label}
{element}
','questionLevel'); + // ------------------------------- + // Enrich question + // ------------------------------- $form->addRule('questionName', get_lang('GiveQuestion'), 'required'); // default content @@ -1071,10 +1174,7 @@ abstract class Question $form -> addElement('html',''); @@ -1084,31 +1184,52 @@ abstract class Question $renderer->setElementTemplate('
{label}
{element}
','questionDescription'); + // ------------------------------- + // Advanced parameters + // ------------------------------- + // question level + //@todo move levles into a table + $select_level = array (1,2,3,4,5); + //$radios_results_enabled[] = + foreach($select_level as $val) { + $radios_results_enabled[] = FormValidator :: createElement ('radio', null, null,$val,$val); + } + $form->addGroup($radios_results_enabled,'questionLevel',get_lang('Difficulty')); + // HUB 12-10-2011 + // categories + $tabCat = array(); + $tabCat = Testcategory::getCategoriesIdAndName(); + $form->addElement('select', 'questionCategory', get_lang('Category'), $tabCat); + // note always positive for multiple answer questions + // Form's style + $renderer->setElementTemplate('
{label}
{element}
 ','questionName'); + $renderer->setElementTemplate('
 '.get_lang("AdvancedParameters").'
 
','questionCategory'); + // fhub // hidden values $form->addElement('hidden','myid',$_REQUEST['myid']); - - - if (!isset($_GET['fromExercise'])) { - switch($answerType) { - case 1: $this->question = get_lang('langDefaultUniqueQuestion'); break; - case 2: $this->question = get_lang('langDefaultMultipleQuestion'); break; - case 3: $this->question = get_lang('langDefaultFillBlankQuestion'); break; - case 4: $this->question = get_lang('langDefaultMathingQuestion'); break; - case 5: $this->question = get_lang('langDefaultOpenQuestion'); break; - case 9: $this->question = get_lang('langDefaultMultipleQuestion'); break; - } - } + if (!isset($_GET['fromExercise'])) { + switch($answerType) { + case 1: $this->question = get_lang('langDefaultUniqueQuestion'); break; + case 2: $this->question = get_lang('langDefaultMultipleQuestion'); break; + case 3: $this->question = get_lang('langDefaultFillBlankQuestion'); break; + case 4: $this->question = get_lang('langDefaultMathingQuestion'); break; + case 5: $this->question = get_lang('langDefaultOpenQuestion'); break; + case 9: $this->question = get_lang('langDefaultMultipleQuestion'); break; + } + } $form->addElement('html','
'); // default values $defaults = array(); $defaults['questionName'] = $this -> question; $defaults['questionDescription'] = $this -> description; $defaults['questionLevel'] = $this -> level; - - //Came from he question pool - if (isset($_GET['fromExercise'])) { - $form->setDefaults($defaults); - } + $defaults['questionCategory'] = $this->category; // hub 12-10-2011 + + //Came from he question pool + if (isset($_GET['fromExercise'])) { + $form->setDefaults($defaults); + } if (!empty($_REQUEST['myid'])) { $form->setDefaults($defaults); @@ -1126,13 +1247,13 @@ abstract class Question */ function processCreation ($form, $objExercise) { $this -> updateTitle($form->getSubmitValue('questionName')); - $this -> updateDescription($form->getSubmitValue('questionDescription')); - $this -> updateLevel($form->getSubmitValue('questionLevel')); - $this -> save($objExercise -> id); - // modify the exercise - $objExercise->addToList($this -> id); - $objExercise->update_question_positions(); - + $this -> updateDescription($form->getSubmitValue('questionDescription')); + $this -> updateLevel($form->getSubmitValue('questionLevel')); + $this->updateCategory($form->getSubmitValue('questionCategory')); // hub 12-10-2011 + $this -> save($objExercise -> id); + // modify the exercise + $objExercise->addToList($this -> id); + $objExercise->update_question_positions(); } /** @@ -1171,7 +1292,7 @@ abstract class Question if (isset($exerciseId) && !empty($exerciseId)) { $TBL_LP_ITEM = Database::get_course_table(TABLE_LP_ITEM); $sql="SELECT max_score FROM $TBL_LP_ITEM - WHERE c_id = ".api_get_course_int_id()." AND item_type = '".TOOL_QUIZ."' AND path ='".Database::escape_string($exerciseId)."'"; + WHERE item_type = '".TOOL_QUIZ."' AND path ='".Database::escape_string($exerciseId)."'"; $result = Database::query($sql); if (Database::num_rows($result) > 0) { $show_quiz_edition = false; @@ -1183,14 +1304,13 @@ abstract class Question foreach ($question_type_custom_list as $i=>$a_type) { // include the class of the type require_once($a_type[0]); - // get the picture of the type and the langvar which describes it - $img = $explanation = ''; + // get the picture of the type and the langvar which describes it + $img = $explanation = ''; eval('$img = '.$a_type[1].'::$typePicture;'); eval('$explanation = get_lang('.$a_type[1].'::$explanationLangVar);'); echo '
  • '; echo '
    '; if ($show_quiz_edition) { - echo ''.Display::return_icon($img, $explanation).''; //echo '
    '; //echo ''.$explanation.''; @@ -1199,7 +1319,6 @@ abstract class Question $img = $img['filename']; echo ''.Display::return_icon($img.'_na.gif',$explanation).''; //echo '
    '; - //echo ''.$explanation.''; } echo '
    '; @@ -1235,8 +1354,7 @@ abstract class Question } static function saveQuestionOption($question_id, $name, $position = 0) { - $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $params['c_id'] = api_get_course_int_id(); + $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); $params['question_id'] = intval($question_id); $params['name'] = $name; $params['position'] = $position; @@ -1247,12 +1365,12 @@ abstract class Question static function deleteAllQuestionOptions($question_id) { $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - Database::delete($TBL_EXERCICE_QUESTION_OPTION, array('question_id = ? AND c_id = ?' => array($question_id, api_get_course_int_id()))); + Database::delete($TBL_EXERCICE_QUESTION_OPTION, array('question_id = ?'=> $question_id)); } static function updateQuestionOption($id, $params) { $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $result = Database::update($TBL_EXERCICE_QUESTION_OPTION, $params, array('id = ? AND c_id = ? '=>array($id, api_get_course_int_id()))); + $result = Database::update($TBL_EXERCICE_QUESTION_OPTION, $params, array('id = ?'=>$id)); return $result; } @@ -1263,7 +1381,7 @@ abstract class Question } else { $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION, $db_name); } - $result = Database::select('*', $TBL_EXERCICE_QUESTION_OPTION, array('where'=>array('question_id = ? AND c_id = ? ' =>array($question_id, api_get_course_int_id())), 'order'=>'id ASC')); + $result = Database::select('*', $TBL_EXERCICE_QUESTION_OPTION, array('where'=>array('question_id = ?' =>$question_id), 'order'=>'id ASC')); return $result; } @@ -1294,15 +1412,15 @@ abstract class Question $sql = "SELECT max(position) as max_position" ." FROM $tbl_quiz_question q INNER JOIN $tbl_quiz_rel_question r" ." ON q.id = r.question_id" - ." AND exercice_id = $quiz_id AND q.c_id = ".api_get_course_int_id()." AND r.c_id = ".api_get_course_int_id(); - $rs_max = Database::query($sql); + ." AND exercice_id = $quiz_id"; + $rs_max = Database::query($sql, __FILE__, __LINE__); $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(".api_get_course_int_id().", '".Database::escape_string($question_name)."'," + ." (question,ponderation,position,type,level) " + ." VALUES('".Database::escape_string($question_name)."'," ." $max_score , $max_position, $type, $level)"; $rs = Database::query($sql); // Get the question ID @@ -1315,10 +1433,23 @@ abstract class Question $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(".api_get_course_int_id().", $question_id, $quiz_id, $max_order)"; + ."(question_id,exercice_id,question_order)" + ." VALUES($question_id, $quiz_id, $max_order)"; $rs = Database::query($sql); return $question_id; } + + /** + * return the image filename of the question type + * + */ + public function get_type_icon_html() { + $type = $this->selectType(); + $tabQuestionList = Question::get_types_information(); // [0]=file to include [1]=type name + require_once($tabQuestionList[$type][0]); + eval('$img = '.$tabQuestionList[$type][1].'::$typePicture;'); + eval('$explanation = get_lang('.$tabQuestionList[$type][1].'::$explanationLangVar);'); + return array($img, $explanation); + } } endif; diff --git a/main/exercice/question_list_admin.inc.php b/main/exercice/question_list_admin.inc.php index c6390bf77b..108bdc3dbc 100644 --- a/main/exercice/question_list_admin.inc.php +++ b/main/exercice/question_list_admin.inc.php @@ -13,6 +13,7 @@ * It is included from the script admin.php * * @author Olivier Brouckaert +* Modified by Hubert Borderiou 21-10-2011 (Question by category) */ // ALLOWED_TO_INCLUDE is defined in admin.php @@ -142,65 +143,120 @@ $token = Security::get_token(); //deletes a session when using don't know question type (ugly fix) unset($_SESSION['less_answer']); -echo '
    '; - -if ($nbrQuestions) { - $my_exercise = new Exercise(); - //forces the query to the database - $my_exercise->read($_GET['exerciseId']); - $questionList=$my_exercise->selectQuestionList(); - - if (is_array($questionList)) { - foreach($questionList as $id) { - //To avoid warning messages - if (!is_numeric($id)) { - continue; - } - $objQuestionTmp = Question :: read($id); - $question_class = get_class($objQuestionTmp); - - $clone_link = ''.Display::return_icon('cd.gif',get_lang('Copy'), array(), 22).''; - $edit_link = ''.Display::return_icon('edit.png',get_lang('Modify'), array(), 22).''; - // this variable $show_quiz_edition comes from admin.php blocks the exercise/quiz modifications - if ($show_quiz_edition) { - $delete_link = ''.Display::return_icon('delete.png',get_lang('Delete'), array(), 22).''; - } - $clone_link = Display::tag('div',$clone_link, array('style'=>'float:left; padding:0px; margin:0px')); - $edit_link = Display::tag('div',$edit_link, array('style'=>'float:left; padding:0px; margin:0px')); - $delete_link = Display::tag('div',$delete_link, array('style'=>'float:left; padding:0px; margin:0px')); - $actions = Display::tag('div',$edit_link.$clone_link.$delete_link, array('class'=>'edition','style'=>'width:100px; right:10px; margin-top: 0px; position: absolute; top: 10%;')); - - echo '
    '; - echo '
    '; - $move = Display::return_icon('move.png',get_lang('Move'), array('class'=>'moved', 'style'=>'margin-bottom:-0.5em;')); - $level = ''; - if (!empty($objQuestionTmp->level)) { - $level = '('.get_lang('Difficulty').' '.$objQuestionTmp->level.')'; - } - $title = Security::remove_XSS($objQuestionTmp->selectTitle()); - echo Display::tag('span', ''.$move.' '.cut($title, 80).' '.Display::tag('span', $level.' ['.get_lang('QualificationNumeric').': '.$objQuestionTmp->selectWeighting().']', array('style'=>"right:110px; position: absolute;padding-top: 0.3em;")).'', array('style'=>'')); - echo $actions; - echo '
    '; - - echo '
    '; - echo '

    '; - //echo get_lang($question_class.$label); - echo get_lang($question_class); - echo '
    '; - //echo get_lang('Level').': '.$objQuestionTmp->selectLevel(); - echo '
    '; - showQuestion($id, false, '', '',false, true); - echo '

    '; - echo '
    '; - echo '
    '; - - unset($objQuestionTmp); +// If we are in a test +$inATest = isset($exerciseId) && $exerciseId > 0; +if (!$inATest) { + echo get_lang("ChoiceQuestionType"); +} +else { + echo '
    '; + if ($nbrQuestions) { + $my_exercise = new Exercise(); + //forces the query to the database + $my_exercise->read($_GET['exerciseId']); + $questionList=$my_exercise->selectQuestionList(); + // ----------------------- + // Style for columns + // ----------------------- + $styleQuestion = "width:50%; float:left;"; + $styleType = "width:4%; float:left; padding-top:4px; text-align:center;"; + $styleCat = "width:22%; float:left; padding-top:8px; text-align:center;"; + $styleLevel = "width:6%; float:left; padding-top:8px; text-align:center;"; + $styleScore = "width:4%; float:left; padding-top:8px; text-align:center;"; + $styleAction = "width:10%; float:left; padding-top:8px;"; + // ------------- + // Title line + // ------------- + echo "
    "; + echo "
     ".get_lang('Questions')."
    "; + echo "
    ".get_lang('Type')."
    "; + echo "
    ".get_lang('Category')."
    "; + echo "
    ".get_lang('Difficulty')."
    "; + echo "
    ".get_lang('Score')."
    "; + echo "
    "; + echo "
     
    "; + // ------------- + if (is_array($questionList)) { + foreach($questionList as $id) { + //To avoid warning messages + if (!is_numeric($id)) { + continue; + } + $objQuestionTmp = Question :: read($id); + $question_class = get_class($objQuestionTmp); + + $clone_link = ''.Display::return_icon('cd.gif',get_lang('Copy'), array(), 22).''; + $edit_link = ''.Display::return_icon('edit.png',get_lang('Modify'), array(), 22).''; + // this variable $show_quiz_edition comes from admin.php blocks the exercise/quiz modifications + if ($show_quiz_edition) { + $delete_link = ''.Display::return_icon('delete.png',get_lang('RemoveFromTest'), array(), 22).''; + } + $edit_link = Display::tag('div',$edit_link, array('style'=>'float:left; padding:0px; margin:0px')); + $clone_link = Display::tag('div',$clone_link, array('style'=>'float:left; padding:0px; margin:0px')); + $delete_link = Display::tag('div',$delete_link, array('style'=>'float:left; padding:0px; margin:0px')); + $actions = Display::tag('div',$edit_link.$clone_link.$delete_link, array('class'=>'edition','style'=>'width:100px; right:10px; margin-top: 0px; position: absolute; top: 10%;')); + + $title = Security::remove_XSS($objQuestionTmp->selectTitle()); + $move = Display::return_icon('move.png',get_lang('Move'), array('class'=>'moved', 'style'=>'margin-bottom:-0.5em;')); + // --------------------- + // Question name + // --------------------- + $questionName = Display::tag('div', ''.$move.' '.cut($title, 60).'', array('style'=>$styleQuestion)); + // --------------------- + // Question type + // --------------------- + $tabQuestionList = Question::get_types_information(); + list($typeImg, $typeExpl) = $objQuestionTmp->get_type_icon_html(); + $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array('style'=>$styleType)); + // --------------------- + // Question category + // --------------------- + $txtQuestionCat = Security::remove_XSS(Testcategory::getCategoryNameForQuestion($objQuestionTmp->id)); + if (empty($txtQuestionCat)) { + $txtQuestionCat = "-"; + } + $questionCategory = Display::tag('div', ''.cut($txtQuestionCat, 55).'', array('style'=>$styleCat)); + // --------------------- + // Question level + // --------------------- + $txtQuestionLevel = $objQuestionTmp->level; + if (empty($objQuestionTmp->level)) { + $txtQuestionLevel = '-'; + } + $questionLevel = Display::tag('div', $txtQuestionLevel, array('style'=>$styleLevel)); + // --------------------- + // Question score + // --------------------- + $questionScore = Display::tag('div', $objQuestionTmp->selectWeighting(), array('style'=>$styleScore)); + // --------------------- + echo '
    '; + echo '
    '; + echo $questionName; + echo $questionType; + echo $questionCategory; + echo $questionLevel; + echo $questionScore; + echo $actions; + echo '
    '; + echo '
    '; + echo '

    '; + //echo get_lang($question_class.$label); + echo get_lang($question_class); + echo '
    '; + //echo get_lang('Level').': '.$objQuestionTmp->selectLevel(); + echo '
    '; + showQuestion($id, false, '', '',false, true); + echo '

    '; + echo '
    '; + echo '
    '; + unset($objQuestionTmp); + } + echo '
    '; } - echo '
    '; } -} -if(!$nbrQuestions) { - echo Display::display_warning_message(get_lang('NoQuestion')); -} - -echo ''; \ No newline at end of file + if(!$nbrQuestions) { + echo Display::display_warning_message(get_lang('NoQuestion')); + } + + echo ''; +} \ No newline at end of file diff --git a/main/exercice/question_pool.php b/main/exercice/question_pool.php index 29c6e8cf1a..24ecd12e5c 100644 --- a/main/exercice/question_pool.php +++ b/main/exercice/question_pool.php @@ -8,6 +8,7 @@ * @package chamilo.exercise * @author Olivier Brouckaert * @author Julio Montoya adding support to query all questions from all session, courses, exercises +* Modify by hubert borderiou 2011-10-21 Question's category */ /** * Code @@ -23,7 +24,7 @@ require_once '../inc/global.inc.php'; $this_section = SECTION_COURSES; -$is_allowedToEdit = api_is_allowed_to_edit(null,true); +$is_allowedToEdit=api_is_allowed_to_edit(null,true); if (empty($delete)) { $delete = intval($_GET['delete']); @@ -34,12 +35,14 @@ if ( empty ( $recup ) ) { if ( empty ( $fromExercise ) ) { $fromExercise = intval($_REQUEST['fromExercise']); } - -$exerciseId = null; if(isset($_GET['exerciseId'])){ $exerciseId = intval($_GET['exerciseId']); } +if (isset($_GET['courseCategoryId'])) { + $courseCategoryId = intval($_GET['courseCategoryId']); +} + $exerciseLevel = -1; if(isset($_REQUEST['exerciseLevel'])){ $exerciseLevel = intval($_REQUEST['exerciseLevel']); @@ -56,17 +59,15 @@ if(!empty($_GET['copy_question'])){ $copy_question = intval($_GET['copy_question']); } -//only that type of question -if(!empty($_GET['type'])){ - $type = intval($_GET['type']); -} +$session_id = intval($_GET['session_id']); +$selected_course = intval($_GET['selected_course']); +$course_id_changed = intval($_GET['course_id_changed']); // save the id of the previous course selected by user to reset menu if we detect that user change course hub 13-10-2011 +$exercice_id_changed = intval($_GET['exercice_id_changed']); // save the id of the previous exercice selected by user to reset menu if we detect that user change course hub 13-10-2011 -$session_id = intval($_GET['session_id']); -$selected_course = intval($_GET['selected_course']); - - -// maximum number of questions on a same page -$limitQuestPage = 20; +// by default when we go to the page for the first time, we select the current course +if (!isset($_GET['selected_course']) && !isset($_GET['exerciseId'])) { + $selected_course = api_get_course_int_id(); +} // document path $documentPath = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document'; @@ -82,65 +83,56 @@ $nameTools = get_lang('QuestionPool'); $interbreadcrumb[] = array("url" => "exercice.php","name" => get_lang('Exercices')); $interbreadcrumb[] = array("url" => "admin.php?exerciseId=".$objExercise->id, "name" => $objExercise->name); +$displayMessage = ""; // messag to be displayed if actions succesfull if ($is_allowedToEdit) { - //Duplicating a Question - if (!isset($_POST['recup']) && $copy_question != 0 && isset($fromExercise)) { - $origin_course_id = intval($_GET['course_id']); - $origin_course_info = api_get_course_info_by_id($origin_course_id); - $current_course = api_get_course_info(); - $old_question_id = $copy_question; - - //Reading the source question + $origin_course_id = intval($_GET['course_id']); + $origin_course_info = api_get_course_info_by_id($origin_course_id); + $current_course = api_get_course_info(); + $old_question_id = $copy_question; + //Reading the source question $old_question_obj = Question::read($old_question_id, $origin_course_id); if ($old_question_obj) { $old_question_obj->updateTitle($old_question_obj->selectTitle().' - '.get_lang('Copy')); - - //Duplicating the source question, in the current course + //Duplicating the source question, in the current course $new_id = $old_question_obj->duplicate($current_course); - - //Reading new question + //Reading new question $new_question_obj = Question::read($new_id); - $new_question_obj->addToList($fromExercise); - - //Reading Answers obj of the current course + //Reading Answers obj of the current course $new_answer_obj = new Answer($old_question_id, $origin_course_id); $new_answer_obj->read(); - - //Duplicating the Answers in the current course + //Duplicating the Answers in the current course $new_answer_obj->duplicate($new_id, $current_course); - // destruction of the Question object unset($new_question_obj); unset($old_question_obj); - - if (!$objExcercise instanceOf Exercise) { - $objExercise = new Exercise(); - $objExercise->read($fromExercise); - } + if (!$objExcercise instanceOf Exercise) { + $objExercise = new Exercise(); + $objExercise->read($fromExercise); + } api_session_register('objExercise'); } - header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); - exit(); + $displayMessage = get_lang('ItemAdded'); +// header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); +// exit(); } - - // deletes a question from the data base and all exercises + // deletes a question from the database and all exercises if ($delete) { // construction of the Question object // if the question exists - if($objQuestionTmp = Question::read($delete)) { + if($objQuestionTmp = Question::read($delete)) + { // deletes the question from all exercises $objQuestionTmp->delete(); } // destruction of the Question object unset($objQuestionTmp); - } elseif($recup && $fromExercise) { - /* + } + elseif($recup && $fromExercise) { // gets an existing question and copies it into a new exercise $objQuestionTmp = Question :: read($recup); - // if the question exists if($objQuestionTmp = Question :: read($recup)) { // adds the exercise ID represented by $fromExercise into the list of exercises for the current question @@ -156,9 +148,11 @@ if ($is_allowedToEdit) { // adds the question ID represented by $recup into the list of questions for the current exercise $objExercise->addToList($recup); api_session_register('objExercise'); - header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); - exit();*/ - } else if( isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) { + +// header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); +// exit(); + } + else if( isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) { $list_recup = $_POST['recup']; foreach ($list_recup as $course_id => $question_data) { @@ -216,8 +210,8 @@ if ($is_allowedToEdit) { } } api_session_register('objExercise'); - header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); - exit(); +// header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); +// exit(); } } @@ -234,25 +228,55 @@ if (!$is_allowedToEdit) { api_not_allowed(true); } -$htmlHeadXtra[] = ' '; + + function mark_course_id_changed() { + $('#course_id_changed').val('1'); + } + + function mark_exercice_id_changed() { + $('#exercice_id_changed').val('1'); + } + + function confirm_your_choice() { + return confirm('$confirmYourChoice'); + } + +"; + Display::display_header($nameTools,'Exercise'); // Menu echo '
    '; -if (isset($type)) { - $url = api_get_self().'?type=1'; -} else { - $url = api_get_self(); -} -echo ''.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').''; + if (isset($type)) { + $url = api_get_self().'?type=1'; + } else { + $url = api_get_self(); + } + if (isset($fromExercise) && $fromExercise > 0) { + echo ''.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'','32').''; + $titleAdd = get_lang('addQuestionToTest'); + } + else { + echo ''.Display::return_icon('back.png', get_lang('BackToExercisesList'),'','32').''; + echo "".Display::return_icon('add_question.gif', get_lang('NewQu'), '', 32).""; + $titleAdd = get_lang('manageAllQuestions'); + } echo '
    '; +if ($displayMessage != "") { + Display::display_confirmation_message($displayMessage); + $displayMessage = ""; +} + //Title -echo '

    '.$nameTools.'

    '; +echo '

    '.$nameTools.' - '.$titleAdd.'

    '; //Form echo '
    '; @@ -261,70 +285,107 @@ if (isset($type)) { } echo ''; -//Session list +// ---------------------------------------------------- +// Session list, if sessions are used. +// ---------------------------------------------------- $session_list = SessionManager::get_sessions_by_coach(api_get_user_id()); - +// hub 13-10-2011 +$tabAttrParam = array('class'=>'chzn-select', 'onchange'=>'submit_form(this)'); // when sessions are used +$labelFormRow = get_lang('Session'); +if (api_get_setting('use_session_mode') == 'false') { + $tabAttrParam = array('style'=>'visibility:hidden', 'onchange'=>'submit_form(this)'); + $labelFormRow = ""; +} $session_select_list = array(); foreach($session_list as $item) { - $session_select_list[$item['id']] = $item['name']; + $session_select_list[$item['id']] = $item['name']; } -$select_session_html = Display::select('session_id', $session_select_list, $session_id, array('class'=>'chzn-select','onchange'=>'submit_form(this);')); -echo Display::form_row(get_lang('Session'), $select_session_html); - -//Course list - -if (!empty($session_id) && $session_id != '-1') { - $course_list = SessionManager::get_course_list_by_session_id($session_id); -} else { - $course_list = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id()); +$select_session_html = Display::select('session_id', $session_select_list, $session_id, $tabAttrParam); // hub 13-10-2011 +echo Display::form_row($labelFormRow, $select_session_html); // hub 13-10-2011 + +// ----------------------------------------------------------------------------- +// Course list, get course list of session, or for course where user is admin +// ----------------------------------------------------------------------------- +if (!empty($session_id) && $session_id != '-1') { + $course_list = SessionManager::get_course_list_by_session_id($session_id); +} else { + $course_list = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id()); } - $course_select_list = array(); foreach ($course_list as $item) { - $course_select_list[$item['id']] = $item['title']; -} + $course_select_list[$item['id']] = ""; + if ($item['id'] == api_get_course_int_id()) { + $course_select_list[$item['id']] = ">    "; + } + $course_select_list[$item['id']] .= $item['title']; +} -$select_course_html = Display::select('selected_course', $course_select_list, $selected_course, array('class'=>'chzn-select','onchange'=>'submit_form(this);')); +$select_course_html = Display::select('selected_course', $course_select_list, $selected_course, array('class'=>'chzn-select','onchange'=>'mark_course_id_changed(); submit_form(this);')); echo Display::form_row(get_lang('Course'), $select_course_html); - +$db_name = ""; if (empty($selected_course) || $selected_course == '-1') { - $course_info = api_get_course_info(); -} else { - $course_info = CourseManager::get_course_information_by_id($selected_course); + $course_info = api_get_course_info(); + reset_menu_exo_lvl_type(); // no course selected, reset menu test / difficulté / type de reponse // hub 13-10-2011 +} +else { + $course_info = CourseManager::get_course_information_by_id($selected_course); +} +// If course has changed, reset the menu default +if ($course_id_changed) { + reset_menu_exo_lvl_type(); } $course_id = $course_info['real_id']; - //Redefining table calls $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST); $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER); +$TBL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); // hub 13-10-2011 +$TBL_COURSE_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); // hub 13-10-2011 + -$exercise_list = get_all_exercises($course_info, $session_id); +// --------------------------------------------- +// Get course categories for the selected course +// --------------------------------------------- +// get category list for the course $selected_course +$tabCatList = Testcategory::getCategoriesIdAndName($selected_course); +$selectCourseCateogry = Display::select('courseCategoryId', $tabCatList, $courseCategoryId, array('class'=>'chzn-select','onchange'=>'submit_form(this);'), false); +echo Display::form_row(get_lang("QuestionCategory"), $selectCourseCateogry); +// --------------------------------------------- +// Get exercice list for this course +// --------------------------------------------- +$exercise_list = get_all_exercises_for_course_id($course_info, $session_id, $selected_course); //Exercise List $my_exercise_list = array(); $my_exercise_list['0'] = get_lang('AllExercises'); $my_exercise_list['-1'] = get_lang('OrphanQuestions'); - if (is_array($exercise_list)) { - foreach($exercise_list as $row) { - if ($row['id'] != $fromExercise) { - $my_exercise_list[$row['id']] = $row['title']; - } - } + foreach($exercise_list as $row) { + $my_exercise_list[$row['id']] = ""; + if ($row['id'] == $fromExercise && $selected_course == api_get_course_int_id()) { + $my_exercise_list[$row['id']] = ">    "; // hub 13-10-2011 + } + $my_exercise_list[$row['id']] .= $row['title']; + } } -$select_exercise_html = Display::select('exerciseId', $my_exercise_list, $exerciseId, array('class'=>'chzn-select','onchange'=>'submit_form(this);'), false); +if ($exercice_id_changed == 1) { + reset_menu_lvl_type(); +} +$select_exercise_html = Display::select('exerciseId', $my_exercise_list, $exerciseId, array('class'=>'chzn-select','onchange'=>'mark_exercice_id_changed(); submit_form(this);'), false); echo Display::form_row(get_lang('Exercise'), $select_exercise_html); -//Difficulty list (only from 0 to 5) +// --------------------------------------------- +// Difficulty list (only from 0 to 5) +// --------------------------------------------- $select_difficulty_html = Display::select('exerciseLevel', array(-1 => get_lang('All'), 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5), $exerciseLevel, array('class'=>'chzn-select', 'onchange'=>'submit_form(this);'), false); echo Display::form_row(get_lang('Difficulty'), $select_difficulty_html); -//Answer type - +// --------------------------------------------- +// Answer type +// --------------------------------------------- $question_list = Question::get_types_information(); $new_question_list = array(); $new_question_list['-1'] = get_lang('All'); @@ -348,267 +409,323 @@ $select_answer_html = Display::select('answerType', $new_question_list, $answerT echo Display::form_row(get_lang('AnswerType'), $select_answer_html); $button = ''; echo Display::form_row('', $button); +echo ""; // hub 13-10-2011 +echo ""; // hub 13-10-2011 ?>
    '; -echo ''; -$from = $page * $limitQuestPage; - -$show_pagination = true; +// -------------------------------------------------------- // if we have selected an exercise in the list-box 'Filter' +// -------------------------------------------------------- if ($exerciseId > 0) { - //Specific exercise $where = ''; - if (isset($type) && $type==1) { - $where = ' type = 1 AND '; + $from = ''; + if (isset($courseCategoryId) && $courseCategoryId > 0) { + $from = ", $TBL_COURSE_REL_CATEGORY crc "; + $where .= " AND crc.c_id=$selected_course AND crc.question_id=qu.id AND crc.category_id=$courseCategoryId"; } if (isset($exerciseLevel) && $exerciseLevel != -1) { - $where .= ' level='.$exerciseLevel.' AND '; + $where .= ' AND level='.$exerciseLevel; } if (isset($answerType) && $answerType != -1) { - $where .= ' type='.$answerType.' AND '; - } - $sql = "SELECT id, question, type, level - FROM $TBL_EXERCICE_QUESTION eq, $TBL_QUESTIONS q - WHERE $where question_id=id AND exercice_id='".$exerciseId."' AND eq.c_id = $course_id AND q.c_id = $course_id - ORDER BY question_order"; - $result=Database::query($sql); - while($row = Database::fetch_array($result, 'ASSOC')) { - $main_question_list[] = $row; - } -} elseif($exerciseId == -1) { - //Orphan - $type_where= ''; - if (isset($type) && $type==1) { - $type_where = ' AND questions.type = 1 '; + $where .= ' AND type='.$answerType; } + $sql = "SELECT DISTINCT id,question,type,level FROM $TBL_EXERCICE_QUESTION qt,$TBL_QUESTIONS qu $from WHERE qt.question_id=qu.id AND qt.exercice_id=$exerciseId AND qt.c_id=$selected_course AND qu.c_id=$selected_course $where ORDER BY question_order"; + $result=Database::query($sql); + while($row = Database::fetch_array($result, 'ASSOC')) { + $main_question_list[] = $row; + } +} +elseif ($exerciseId == -1) { + // --------------------------------------------------------------------------- + // if we have selected the option 'Orphan questions' in the list-box 'Filter' + // --------------------------------------------------------------------------- $level_where = ''; + $from = ''; + if (isset($courseCategoryId) && $courseCategoryId > 0) { + $from = ", $TBL_COURSE_REL_CATEGORY crc "; + $level_where .= " AND crc.c_id=$selected_course AND crc.question_id=qu.id AND crc.category_id=$courseCategoryId"; + } if (isset($exerciseLevel) && $exerciseLevel!= -1 ) { - $level_where = ' level='.$exerciseLevel.' AND '; + $level_where = ' AND level='.$exerciseLevel; } $answer_where = ''; if (isset($answerType) && $answerType != -1 ) { - $answer_where = ' questions.type='.$answerType.' AND '; + $answer_where = ' AND type='.$answerType; } - $sql = 'SELECT questions.id, questions.question, questions.type, quizz_questions.exercice_id , level, session_id - FROM '.$TBL_QUESTIONS.' as questions LEFT JOIN '.$TBL_EXERCICE_QUESTION.' as quizz_questions - ON questions.id=quizz_questions.question_id LEFT JOIN '.$TBL_EXERCICES.' as exercices - ON exercice_id=exercices.id - WHERE '.$answer_where.' '.$level_where.' (quizz_questions.exercice_id IS NULL OR exercices.active = -1 ) '.$type_where.' AND - questions.c_id = '.$course_id.' - - LIMIT '.$from.', '.($limitQuestPage + 1); - $result = Database::query($sql); - - while($row = Database::fetch_array($result, 'ASSOC')) { - $main_question_list[] = $row; - } -} else { - //All tests - $show_pagination = false; - + $sql = "SELECT DISTINCT * FROM `chamilo19_main`.`c_quiz_question` AS qu $from WHERE qu.c_id=$selected_course AND qu.id NOT IN (SELECT question_id FROM `chamilo19_main`.`c_quiz_rel_question` WHERE c_id=$selected_course ) $level_where $answer_where"; + $result = Database::query($sql); + while($row = Database::fetch_array($result, 'ASSOC')) { + $main_question_list[] = $row; + } +} +else { + // --------------------------------- + // All tests for selected course + // --------------------------------- // if we have not selected any option in the list-box 'Filter' $filter = ''; - if (isset($type) && $type==1){ - $filter .= ' AND qu.type = 1 '; - } + $from = ''; + if (isset($courseCategoryId) && $courseCategoryId > 0) { + $from = ", $TBL_COURSE_REL_CATEGORY crc "; + $filter .= " AND crc.c_id=$selected_course AND crc.question_id=qu.id AND crc.category_id=$courseCategoryId"; + } if (isset($exerciseLevel) && $exerciseLevel != -1) { $filter .= ' AND level='.$exerciseLevel.' '; } if (isset($answerType) && $answerType != -1) { $filter .= ' AND qu.type='.$answerType.' '; - } - if ($objExercise->feedbacktype != EXERCISE_FEEDBACK_TYPE_DIRECT) { - $filter .= ' AND qu.type <> '.HOT_SPOT_DELINEATION.' '; - } - $new_limit_page = $limitQuestPage + 1; - - if (!empty($session_id) && $session_id != '-1') { - $main_question_list = array(); - if (!empty($course_list)) - foreach ($course_list as $course_item) { - if (!empty($selected_course) && $selected_course != '-1') { - if ($selected_course != $course_item['id']) { + } +// // why these lines ? +// if ($objExercise->feedbacktype != EXERCISE_FEEDBACK_TYPE_DIRECT) { +// $filter .= ' AND qu.type <> '.HOT_SPOT_DELINEATION.' '; +// } +// // fwhy + // -------------------- + // if in session + // -------------------- + if (!empty($session_id) && $session_id != '-1') { + $main_question_list = array(); + if (!empty($course_list)) + foreach ($course_list as $course_item) { + if (!empty($selected_course) && $selected_course != '-1') { + if ($selected_course != $course_item['id']) { + continue; + } + } + $exercise_list = get_all_exercises($course_item, $session_id); + if (!empty($exercise_list)) { + foreach ($exercise_list as $exercise) { + $my_exercise = new Exercise($course_item['id']); + $my_exercise->read($exercise['id']); + if (!empty($my_exercise)) { + if (!empty($my_exercise->questionList)) { + foreach ($my_exercise->questionList as $question_id) { + $question_obj = Question::read($question_id, $course_item['id']); + if ($exerciseLevel != '-1') + if ($exerciseLevel != $question_obj->level) { continue; } - } - $exercise_list = get_all_exercises($course_item, $session_id); - - if (!empty($exercise_list)) { - foreach ($exercise_list as $exercise) { - $my_exercise = new Exercise($course_item['id']); - $my_exercise->read($exercise['id']); - - - if (!empty($my_exercise)) { - - if (!empty($my_exercise->questionList)) { - foreach ($my_exercise->questionList as $question_id) { - - $question_obj = Question::read($question_id, $course_item['id']); - if ($exerciseLevel != '-1') - if ($exerciseLevel != $question_obj->level) { - continue; - } - - if ($answerType != '-1') - if ($answerType != $question_obj->type) { - continue; - } - if ($objExercise->feedbacktype != EXERCISE_FEEDBACK_TYPE_DIRECT) { - if ($question_obj->type == HOT_SPOT_DELINEATION) { - continue; - } - } - $question_row = array( 'id' => $question_obj->id, - 'question' => $question_obj->question, - 'type' => $question_obj->type, - 'level' => $question_obj->level, - 'exercise_id' => $exercise['id'], - 'course_id' => $course_item['id'], - ); - - $main_question_list[] = $question_row; - } - } - } + if ($answerType != '-1') + if ($answerType != $question_obj->type) { + continue; } - } - } - } else { - //By default - $sql = "SELECT qu.id, question, qu.type, level, q.session_id - FROM $TBL_QUESTIONS as qu, $TBL_EXERCICE_QUESTION as qt, $TBL_EXERCICES as q - WHERE qu.c_id = $course_id AND - qu.c_id = $course_id AND - q.id=qt.exercice_id AND - qu.id=qt.question_id AND - qt.exercice_id <> ".$fromExercise." $filter - ORDER BY session_id ASC - LIMIT $from, $new_limit_page"; - $result = Database::query($sql); - - while($row = Database::fetch_array($result, 'ASSOC')) { - $main_question_list[] = $row; - } - } + // hub 23-10-2011 + if ($courseCategoryId > 0 && Testcategory::getCategoryForQuestion($question_obj->id, $selected_course)) { + continue; + } + if ($objExercise->feedbacktype != EXERCISE_FEEDBACK_TYPE_DIRECT) { + if ($question_obj->type == HOT_SPOT_DELINEATION) { + continue; + } + } + $question_row = array( 'id' => $question_obj->id, + 'question' => $question_obj->question, + 'type' => $question_obj->type, + 'level' => $question_obj->level, + 'exercise_id' => $exercise['id'], + 'course_id' => $course_item['id'], + ); + $main_question_list[] = $question_row; + } + } + } + } + } + } + } + else { + // ------------------------------------------------------------ + // All tests for the course selected, not in session + // ------------------------------------------------------------ + $sql = "SELECT DISTINCT qu.id, question, qu.type, level, q.session_id FROM $TBL_QUESTIONS as qu, $TBL_EXERCICE_QUESTION as qt, $TBL_EXERCICES as q $from WHERE qu.c_id=$selected_course AND qt.c_id=$selected_course AND q.c_id=$selected_course AND qu.id = qt.question_id AND q.id = qt.exercice_id $filter ORDER BY session_id ASC"; + $result = Database::query($sql); + while($row = Database::fetch_array($result, 'ASSOC')) { + $main_question_list[] = $row; + } + } // forces the value to 0 $exerciseId=0; } + $nbrQuestions = count($main_question_list); -if ($show_pagination) { - echo '', - ' - '; } -echo ''; - -if (!empty($fromExercise)) { - if (api_get_session_id() == 0 ){ - echo ''; +else { // IN A TEST - IN THE COURSE + if ($selected_course == api_get_course_int_id()) { + $actionLabel = get_lang('Reuse'); + $actionIcon1 = "add"; + $actionIcon2 = ""; + $questionTagA = 1; } - echo '', - '', - ''; -} else { - echo '', - '', - ''; -} -echo ''; -$i=1; - -$session_id = api_get_session_id(); -if (!empty($main_question_list)) -foreach ($main_question_list as $row) { - $my_course_id = 0; - if (isset($row['course_id'])) { - $my_course_id = $row['course_id']; + else { // IN A TEST - NOT IN THE COURSE + $actionLabel = get_lang('Reuse'); + $actionIcon1 = "clone"; + $actionIcon2 = ""; + $questionTagA = 0; } - +} +// ------------------- +// display table +// ------------------- +$header = array(); +$header[] = array(get_lang('Question'), false, array("style"=>"text-align:center")); +$header[] = array(get_lang('Type'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center")); +$header[] = array(get_lang('QuestionCategory'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center")); +$header[] = array(get_lang('Difficulty'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center")); +$header[] = array($actionLabel, false, array("style"=>"text-align:center"), array("style"=>"text-align:center")); +$data = array(); +foreach ($main_question_list as $tabQuestion) { + $row = array(); + $row[] = get_a_tag_for_question($questionTagA, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], $tabQuestion['question']); + $row[] = get_question_type_for_question($selected_course, $tabQuestion['id']); + $row[] = get_question_categorie_for_question($selected_course, $tabQuestion['id']); + $row[] = $tabQuestion['level']; + $row[] = get_action_icon_for_question($actionIcon1, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], $tabQuestion['question'], $selected_course, $courseCategoryId, $exerciseId, $exerciseLevel, $answerType, $session_id)." ".get_action_icon_for_question($actionIcon2, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], $tabQuestion['question'], $selected_course, $courseCategoryId, $exercice_id, $exerciseLevel, $answerType, $session_id); + $data[] = $row; +} +Display :: display_sortable_table($header, $data, array(), array('per_page_default'=>999,'per_page'=>999,'page_nr'=>1)); - // if we come from the exercise administration to get a question, - // don't show the questions already used by that exercise +if (!$nbrQuestions) { + echo get_lang('NoQuestion'); +} - // original recipe - - //if (!$fromExercise || !isset($objExercise) || !($objExercise instanceOf Exercise) || (!$objExercise->isInList($row['id']))) - if (!$fromExercise || !isset($objExercise) || !($objExercise instanceOf Exercise) || (is_array($objExercise->questionList)) ) { - echo ''; - if (api_get_session_id() == 0 ){ - echo ''; - } - echo ' '; - echo ' ', - '', - ''; - echo ''; +if (api_get_session_id() == 0 ){ + echo '
    '; +} +Display::display_footer(); - // skips the last question, that is only used to know if we have or not to create a link "Next page" - if($i == $limitQuestPage) { - break; - } - $i++; + + +// ========================================================================= +// Some functions here, just for question_pool to ease the code +// ========================================================================= + +/* + Put the menu entry for level and type to default "Choice" + It is usefull if you change the exercice, you need to reset the other menus + hubert.borderiou 13-10-2011 +*/ +function reset_menu_lvl_type() { + global $exerciseLevel, $answerType; + $answerType = -1; + $exerciseLevel = -1; +} +/* + Put the menu entry for exercice and level and type to default "Choice" + It is usefull if you change the course, you need to reset the other menus + hubert.borderiou 13-10-2011 +*/ + +function reset_menu_exo_lvl_type() { + global $exerciseId, $courseCategoryId; + reset_menu_lvl_type(); + $exerciseId = 0; + $courseCategoryId = 0; +} + +// +// return the link to admin question, if needed +// hubert.borderiou 13-10-2011 +function get_a_tag_for_question($in_addA, $in_fromex, $in_questionid, $in_questiontype, $in_questionname) { + $res = $in_questionname; + if ($in_addA) { + $res = "".$res.""; } + return $res; } -if (!$nbrQuestions) { - echo '', - '', - ''; +// +// return the html code for delete, add, clone, edit a question +// hubert.borderiou 13-10-2011 +function get_action_icon_for_question($in_action, $from_exercice, $in_questionid, $in_questiontype, $in_questionname, $in_selected_course, $in_courseCategoryId, $in_exercise_id, $in_exerciseLevel, $in_answerType, $in_session_id) { + $res = ""; + $getParams = "&selected_course=$in_selected_course&courseCategoryId=$in_courseCategoryId&exerciseId=$in_exercise_id&exerciseLevel=$in_exerciseLevel&answerType=$in_answerType&session_id=$in_session_id"; + switch ($in_action) { + case "delete" : + $res = ""; + $res .= Display::return_icon("delete.gif", get_lang('Delete')); + $res .= ""; + break; + case "edit" : + $res = get_a_tag_for_question(1, $from_exercice, $in_questionid, $in_questiontype, Display::return_icon("edit.gif", get_lang('Modify'))); + break; + case "add": + // add if question is not already in test + $myObjEx = new Exercise(); + $myObjEx->read($from_exercice); + if (!$myObjEx->isInList($in_questionid)) { + $res = ""; + $res .= Display::return_icon("view_more_stats.gif", get_lang('InsertALinkToThisQuestionInTheExercise')); + $res .= ""; + } + else { + $res = "-"; + } + unset($myObjEx); + break; + case "clone": + $res = ""; + $res .= Display::return_icon('cd.gif', get_lang('ReUseACopyInCurrentTest')); + $res .= ""; + break; + default : + $res = $in_action; + break; + } + return $res; } -echo '
    ', - '', - ' - -
    '; - - if(!empty($page)) { - echo ''; - echo Display::return_icon('action_prev.png'); - echo ' '; - - } elseif($nbrQuestions > $limitQuestPage) { - echo Display::return_icon('action_prev_na.png'); - echo ' '; +// ------------------------------------------------ +// build the line of the array to display questions +// Actions are different if you launch the question_pool page +// They are different too if you have displayed questions from your course +// Or from another course you are the admin(or session admin) +// from a test or not +/* ++--------------------------------------------+--------------------------------------------+ +| NOT IN A TEST | IN A TEST | ++----------------------+---------------------+---------------------+----------------------+ +|IN THE COURSE (*) "x | NOT IN THE COURSE o | IN THE COURSE + | NOT IN THE COURSE o | ++----------------------+---------------------+---------------------+----------------------+ +|Edit the question | Do nothing | Add question to test|Clone question in test| +|Delete the question | | | | +|(true delete) | | | | ++----------------------+---------------------+---------------------+----------------------+ +(*) this is the only way to delete or modify orphan questions +*/ +// ---------------------------------------------------------------------------------------- +if ($fromExercise <= 0) { // NOT IN A TEST - IN THE COURSE + if ($selected_course == api_get_course_int_id()) { + $actionLabel = get_lang('Action'); + $actionIcon1 = "edit"; + $actionIcon2 = "delete"; + $questionTagA = 1; // we are in the course, question title can be a link to the question edit page } - - if($nbrQuestions > $limitQuestPage) { - echo ''; - echo Display::return_icon('action_next.png'); - echo ''; - - } elseif($page) { - echo Display::return_icon('action_next_na.png'); - echo ' '; + else { // NOT IN A TEST - NOT IN THE COURSE + $actionLabel = get_lang('Reuse'); + $actionIcon1 = get_lang('mustBeInATest'); + $actionIcon2 = ""; + $questionTagA = 0; // we are not in this course, to messy if we link to the question in another course } - echo '
    -
    ',get_lang('Question'),'',get_lang('Difficulty'),'',get_lang('Reuse'),'',get_lang('Question'),'',get_lang('Modify'),'',get_lang('Delete'),'
    ',$row['question'],''; - if (empty($fromExercise)) { - echo '',get_lang('Modify'),'', - '', - '',get_lang('Delete'),''; - //'',get_lang('Delete'),''; - } else { - echo $row['level'],''; - - echo ''; - echo ' '.Display::return_icon('cd.gif', get_lang('ReUseACopyInCurrentTest')); - echo ' '; - if ($row['session_id'] == $session_id) { - if ($selected_course == api_get_course_int_id()) { - //echo ''.get_lang('InsertALinkToThisQuestionInTheExercise').''; - } - } - } - echo '
    ',get_lang('NoQuestion'),'
    '; -if (api_get_session_id() == 0 ){ - echo '
    - -
    '; +// +// return the icon for the question type +// hubert.borderiou 13-10-2011 +function get_question_type_for_question($in_selectedcourse, $in_questionid) { + $myObjQuestion = Question::read($in_questionid, $in_selectedcourse); + list($typeImg, $typeExpl) = $myObjQuestion->get_type_icon_html(); + $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array()); + unset($myObjQuestion); + return $questionType; } -Display::display_footer(); + +// +// return the name of the category for the question in a course +// hubert.borderiou 13-10-2011 +function get_question_categorie_for_question($in_courseid, $in_questionid) { + $cat = Testcategory::getCategoryNameForQuestion($in_questionid, $in_courseid); + return $cat; +} \ No newline at end of file diff --git a/main/exercice/testcategory.class.php b/main/exercice/testcategory.class.php new file mode 100644 index 0000000000..d9f0736029 --- /dev/null +++ b/main/exercice/testcategory.class.php @@ -0,0 +1,421 @@ +getCategory($in_id); + $this->id = $tmpobj->id; + $this->name = $tmpobj->name; + $this->description = $tmpobj->description; + } + else { + $this->id = $in_id; + $this->name = $in_name; + $this->description = $in_description; + } + } + + /** return the Testcategory object with id=in_id + */ + function getCategory($in_id) { + $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $in_id = Database::escape_string($in_id); + $sql = "SELECT * FROM $t_cattable WHERE id=$in_id AND c_id=".api_get_course_int_id(); + $res = Database::query($sql); + $numrows = Database::num_rows($res); + if ($numrows > 0) { + $row = Database::fetch_array($res); + $this->id = $row['id']; + $this->name = $row['name']; + $this->description = $row['description']; + } + } + + /** add Testcategory in the database if name doesn't already exists + */ + function addCategoryInBDD() { + $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $v_name = $this->name; + $v_name = Database::escape_string($v_name); + $v_description = $this->description; + $v_description = Database::escape_string($v_description); + // check if name already exists + $sql_verif = "SELECT count(*) AS nb FROM $t_cattable WHERE name = '$v_name' AND c_id=".api_get_course_int_id(); + $result_verif = Database::query($sql_verif, __FILE__, __LINE__); + $data_verif = Database::fetch_array($result_verif); + // lets add in BDD if not the same name + if ($data_verif['nb'] <= 0) { + $c_id = api_get_course_int_id(); + $sql = "INSERT INTO $t_cattable VALUES ('$c_id', '', '$v_name', '$v_description')"; + $res = Database::query($sql, __FILE__, __LINE__); + return true; + } + else { + return false; + } + } + + /** remove catagory with id=in_id from the database if no question use this category + */ + function removeCategory($in_id) { + $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $v_id = Database::escape_string($this->id); + $sql = "DELETE FROM $t_cattable WHERE id=$v_id AND c_id=".api_get_course_int_id(); + $res = Database::query($sql); + if (Database::affected_rows() <= 0) { + return false; + } + else { + return true; + } + } + + + /** modify category name or description of category with id=in_id + */ + function modifyCategory($in_id, $in_name, $in_description) { + $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $v_id = Database::escape_string($this->id); + $v_name = Database::escape_string($this->name); + $v_description = Database::escape_string($this->description); + $sql = "UPDATE $t_cattable SET name='$v_name', description='$v_description' WHERE id='$v_id' AND c_id=".api_get_course_int_id(); + $res = Database::query($sql); + if (Database::affected_rows() <= 0) { + return false; + } + else { + return true; + } + } + + /** get number of question of category id=in_id + */ + function getCategoryQuestionsNumber($in_id) { + $t_reltable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); + $in_id = Database::escape_string($this->id); + $sql = "SELECT count(*) AS nb FROM $t_reltable WHERE category_id=$in_id AND c_id=".api_get_course_int_id(); + $res = Database::query($sql, __FILE__, __LINE__); + $row = Database::fetch_array($res); + return $row['nb']; + } + + + function display($in_color="#E0EBF5") { + echo ""; + } + + + + /** return an array of all Category objects in the database + If in_field=="" Return an array of all category objects in the database + Otherwise, return an array of all in_field value in the database (in_field = id or name or description) + */ + public function getCategoryListInfo($in_field="", $in_courseid="") { + if (empty($in_courseid) || $in_courseid=="") { + $in_courseid = api_get_course_int_id(); + } + $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $in_field = Database::escape_string($in_field); + $tabres = array(); + if ($in_field=="") { + $sql = "SELECT * FROM $t_cattable WHERE c_id=$in_courseid ORDER BY name ASC"; + $res = Database::query($sql); + while ($row = Database::fetch_array($res)) { + $tmpcat = new Testcategory($row['id'], $row['name'], $row['description']); + $tabres[] = $tmpcat; + } + } + else { + $sql = "SELECT $in_field FROM $t_cattable WHERE c_id=$in_courseid ORDER BY $in_field ASC"; + $res = Database::query($sql); + while ($row = Database::fetch_array($res)) { + $tabres[] = $row[$in_field]; + } + } + return $tabres; + } + + + /** + Return the testcategory id for question with question_id = $in_questionid + In this version, a question has only 1 testcategory. + Return the testcategory id, 0 if none + */ + public static function getCategoryForQuestion($in_questionid, $in_courseid="") { + $result = 0; // result + if (empty($in_courseid) || $in_courseid=="") { + $in_courseid = api_get_course_int_id(); + } + $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); + $question_id = Database::escape_string($in_questionid); + $sql = "SELECT category_id FROM $t_cattable WHERE question_id='$question_id' AND c_id=$in_courseid"; + $res = Database::query($sql); + $data = Database::fetch_array($res); + if (Database::num_rows($res) > 0) { + $result = $data['category_id']; + } + return $result; + } + + + /** + * true if question id has a category + */ + public static function isQuestionHasCategory($in_questionid) { + if (Testcategory::getCategoryForQuestion($in_questionid) > 0) { + return true; + } + return false; + } + + + /** + Return the category name for question with question_id = $in_questionid + In this version, a question has only 1 category. + Return the category id, "" if none + */ + function getCategoryNameForQuestion($in_questionid, $in_courseid="") { + if (empty($in_courseid) || $in_courseid=="") { + $in_courseid = api_get_course_int_id(); + } + $catid = Testcategory::getCategoryForQuestion($in_questionid, $in_courseid); + $result = ""; // result + $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $catid = Database::escape_string($catid); + $sql = "SELECT name FROM $t_cattable WHERE id='$catid' AND c_id=$in_courseid"; + $res = Database::query($sql); + $data = Database::fetch_array($res); + if (Database::num_rows($res) > 0) { + $result = $data['name']; + } + return $result; + } + + + + /** + * return the list of differents categories ID for a test + * input : test_id + * return : array of category id (integer) + * hubert.borderiou 07-04-2011 + */ + public static function getListOfCategoriesIDForTest($in_testid) { + // parcourir les questions d'un test, recup les categories uniques dans un tableau + $tabcat = array(); + $quiz = new Exercise(); + $quiz->read($in_testid); + $tabQuestionList = $quiz->selectQuestionList(); + for ($i=0; $i < count($tabQuestionList); $i++) { + if (!in_array(Testcategory::getCategoryForQuestion($tabQuestionList[$i]), $tabcat)) { + $tabcat[] = Testcategory::getCategoryForQuestion($tabQuestionList[$i]); + } + } + return $tabcat; + } + + + /** + * return the list of differents categories NAME for a test + * input : test_id + * return : array of string + * hubert.borderiou 07-04-2011 + */ + public static function getListOfCategoriesNameForTest($in_testid) { + $tabcatName = array(); + $tabcatID = getListOfCategoriesNameForTest($in_testid); + for ($i=0; $i < count($tabcatID); $i++) { + $cat = new Testcategory($tabcatID[$i]); + $tabcatName[] = $cat->name; + } + return $tabcatName; + } + + /** + * return the number of differents categories for a test + * input : test_id + * return : integer + * hubert.borderiou 07-04-2011 + */ + public static function getNumberOfCategoriesForTest($in_testid) { + return count(Testcategory::getListOfCategoriesIDForTest($in_testid)); + } + + + /** + * return the number of question of a category id in a test + * input : test_id, category_id + * return : integer + * hubert.borderiou 07-04-2011 + */ + public static function getNumberOfQuestionsInCategoryForTest($in_testid, $in_categoryid) { + $nbCatResult = 0; + $quiz = new Exercise(); + $quiz->read($in_testid); + $tabQuestionList = $quiz->selectQuestionList(); + for ($i=0; $i < count($tabQuestionList); $i++) { + if (Testcategory::getCategoryForQuestion($tabQuestionList[$i]) == $in_categoryid) { + $nbCatResult++; + } + } + return $nbCatResult; + } + + /** + * return the number of question for a test using random by category + * input : test_id, number of random question (min 1) + * hubert.borderiou 07-04-2011 + * question witout categories are not counted + */ + public static function getNumberOfQuestionRandomByCategory($in_testid, $in_nbrandom) { + $nbquestionresult = 0; + $tabcatid = Testcategory::getListOfCategoriesIDForTest($in_testid); + for ($i=0; $i < count($tabcatid); $i++) { + if ($tabcatid[$i] > 0) { // 0 = no category for this questio + $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($in_testid, $tabcatid[$i]); + if ($nbQuestionInThisCat > $in_nbrandom) { + $nbquestionresult += $in_nbrandom; + } + else { + $nbquestionresult += $nbQuestionInThisCat; + } + } + } + return $nbquestionresult; + } + + + /** + * Return an array (id=>name) + * tabresult[0] = get_lang('NoCategory'); + * + */ + function getCategoriesIdAndName($in_courseid="") { + if (empty($in_courseid) || $in_courseid=="") { + $in_courseid = api_get_course_int_id(); + } + $tabcatobject = Testcategory::getCategoryListInfo("", $in_courseid); + $tabresult = array("0"=>get_lang('NoCategory')); + for ($i=0; $i < count($tabcatobject); $i++) { + $tabresult[$tabcatobject[$i]->id] = $tabcatobject[$i]->name; + } + return $tabresult; + } + + /** + * return an array of question_id for each category + * tabres[0] = array of question id with category id = 0 (i.e. no category) + * tabres[24] = array of question id with category id = 24 + * In this version, a question has 0 or 1 category + */ + function getQuestionsByCat($in_exerciceId) { + $tabres = array(); + $TBL_EXERCICE = Database::get_course_table(TABLE_QUIZ_TEST); + $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); + $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); + $sql = "SELECT qrc.question_id, qrc.category_id FROM $TBL_QUESTION_REL_CATEGORY qrc, $TBL_EXERCICE_QUESTION eq WHERE exercice_id=$in_exerciceId AND eq.question_id=qrc.question_id AND eq.c_id=".api_get_course_int_id()." AND eq.c_id=qrc.c_id ORDER BY category_id, question_id"; + $res = Database::query($sql); + while ($data = Database::fetch_array($res)) { + if (!is_array($tabres[$data['category_id']])) { + $tabres[$data['category_id']] = array(); + } + $tabres[$data['category_id']][] = $data['question_id']; + } + return $tabres; + } + + + /** + * return a tab of $in_number random elements of $in_tab + */ + function getNElementsFromArray($in_tab, $in_number) { + $tabres = $in_tab; + shuffle($tabres); + if ($in_number < count($tabres)) { + $tabres = array_slice($tabres, 0, $in_number); + } + return $tabres; + } + + /** + * display the category + */ + function displayCategoryAndTitle($in_questionID) { + if (Testcategory::getCategoryNameForQuestion($in_questionID) != "") { + echo "
    "; + echo "
    "; + echo get_lang('Category').": ".Testcategory::getCategoryNameForQuestion($in_questionID); + echo "
    "; + echo "
    "; + } + } + + /** + * Display signs [+] and/or (>0) after question title if question has options + * scoreAlwaysPositive and/or uncheckedMayScore + */ + function displayQuestionOption($in_objQuestion) { + if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->scoreAlwaysPositive) { + echo " (>0)"; + } + if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->uncheckedMayScore) { + echo " [+]"; + } + } + + /** + * sortTabByBracketLabel ($tabCategoryQuestions) + * key of $tabCategoryQuestions are the categopy id (0 for not in a category) + * value is the array of question id of this category + * Sort question by Category + */ + function sortTabByBracketLabel($in_tab) { + $tabResult = array(); + $tabCatName = array(); // tab of category name + while (list($cat_id, $tabquestion) = each($in_tab)) { + $catTitle = new Testcategory($cat_id); + $tabCatName[$cat_id] = $catTitle->name; + } + reset($in_tab); + // sort table by value, keeping keys as they are + asort($tabCatName); + // keys of $tabCatName are keys order for $in_tab + while (list($key, $val) = each($tabCatName)) { + $tabResult[$key] = $in_tab[$key]; + } + return $tabResult; + } + + /** + * return total score for test exe_id for all question in the category $in_cat_id for user + * If no question for this category, return "" + */ + public static function getCatScoreForExeidForUserid($in_cat_id, $in_exe_id, $in_user_id) { + $tbl_track_attempt = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); + $tbl_question_rel_category = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); + $query = "SELECT DISTINCT marks, exe_id, user_id, ta.question_id, category_id FROM $tbl_track_attempt ta , $tbl_question_rel_category qrc WHERE ta.question_id=qrc.question_id AND qrc.category_id=$in_cat_id AND exe_id=$in_exe_id AND user_id=$in_user_id"; + $res = Database::query($query); + $totalcatscore = ""; + while ($data = Database::fetch_array($res)) { + $totalcatscore += $data['marks']; + } + return $totalcatscore; + } +} +endif; +?> diff --git a/main/exercice/tests_category.php b/main/exercice/tests_category.php new file mode 100644 index 0000000000..a8861f0f81 --- /dev/null +++ b/main/exercice/tests_category.php @@ -0,0 +1,274 @@ + + function confirmDelete(in_txt, in_id) { + var oldbgcolor = document.getElementById(in_id).style.backgroundColor; + document.getElementById(in_id).style.backgroundColor="#AAFFB0"; + if (confirm(in_txt)) { + return true; + } + else { + document.getElementById(in_id).style.backgroundColor = oldbgcolor; + return false; + } + } + +'; + +// name of the language file that needs to be included +$language_file='exercice'; +$nameTools= ""; + +include('question.class.php'); +include('testcategory.class.php'); +include('../inc/global.inc.php'); +include('exercise.lib.php'); +require_once (api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php'); + +$this_section=SECTION_COURSES; + +if(!api_is_allowed_to_edit()) { + api_not_allowed(true); +} + +// breadcrumbs +$interbreadcrumb[]=array("url" => "exercice.php","name" => get_lang('Exercices')); +Display::display_header(get_lang('Category')); + +// Action handling: add, edit and remove +if (isset($_GET['action']) && $_GET['action'] == 'addcategory') +{ + add_category_form(Security::remove_XSS($_GET['action'])); +} +else if (isset($_GET['action']) && $_GET['action'] == 'editcategory') { + edit_category_form(Security::remove_XSS($_GET['action'])); +} +else if (isset($_GET['action']) && $_GET['action'] == 'deletecategory') { + delete_category_form(Security::remove_XSS($_GET['action'])); +} +else { + display_add_category(); + display_categories(); +} + +Display::display_footer(); + +// ********************************************************************************** +// ****** FUNCTIONS ******************** +// ********************************************************************************** + +// ------------------------------------------------------------------------ +// form to edit a category +// ------------------------------------------------------------------------ +function edit_category_form($in_action) { + + if (isset($_GET['category_id']) && is_numeric($_GET['category_id'])) { + $category_id = Security::remove_XSS($_GET['category_id']); + $objcat = new Testcategory($category_id); + // -------------------- + // initiate the object + // -------------------- + $form = new FormValidator('note','post', api_get_self().'?action='.$in_action.'&category_id='.$category_id); + // -------------------- + // settting the form elements + // -------------------- + $form->addElement('header', '', get_lang('EditCategory')); + $form->addElement('hidden', 'category_id'); + $form->addElement('text', 'category_name', get_lang('CategoryName'),array('size'=>'95')); + $form->addElement('html_editor', 'category_description', get_lang('CategoryDescription'), null, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200')); + $form->addElement('style_submit_button', 'SubmitNote', get_lang('ModifyCategory'), 'class="add"'); + // -------------------- + // setting the defaults + // -------------------- + $defaults = array(); + $defaults["category_id"] = $objcat->id; + $defaults["category_name"] = $objcat->name; + $defaults["category_description"] = $objcat->description; + $form->setDefaults($defaults); + // -------------------- + // setting the rules + // -------------------- + $form->addRule('category_name', '
    '.get_lang('ThisFieldIsRequired'), 'required'); + // -------------------- + // The validation or display + // -------------------- + if ($form->validate()) + { + $check = Security::check_token('post'); + if ($check) { + $values = $form->exportValues(); + $v_id = Security::remove_XSS($values['category_id']); + $v_name = Security::remove_XSS($values['category_name'], COURSEMANAGER); + $v_description = Security::remove_XSS($values['category_description'], COURSEMANAGER); + $objcat = new Testcategory($v_id, $v_name, $v_description); + if ($objcat->modifyCategory()) { + Display::display_confirmation_message(get_lang('MofidfyCategoryDone')); + } + else { + Display::display_confirmation_message(get_lang('ModifyCategoryError')); + } + } + Security::clear_token(); + display_add_category(); + display_categories(); + } + else + { + display_goback(); + $token = Security::get_token(); + $form->addElement('hidden','sec_token'); + $form->setConstants(array('sec_token' => $token)); + $form->display(); + display_categories(); + } + } + else { + Display::display_error_message(get_lang('CannotEditCategory')); + } +} + +// ------------------------------------------------------------------------ +// process to delete a category +// ------------------------------------------------------------------------ +function delete_category_form($in_action) { + if (isset($_GET['category_id']) && is_numeric($_GET['category_id'])) { + $category_id = Security::remove_XSS($_GET['category_id']); + $catobject = new Testcategory($category_id); + if ($catobject->getCategoryQuestionsNumber() == 0) { + if ($catobject->removeCategory()) { + Display::display_confirmation_message(get_lang('DeleteCategoryDone')); + } + else { + Display::display_error_message(get_lang('CannotDeleteCategoryError')); + } + } + else { + Display::display_error_message(get_lang('CannotDeleteCategory')); + } + } + else { + Display::display_error_message(get_lang('CannotDeleteCategoryError')); + } + display_add_category(); + display_categories(); +} + +// ------------------------------------------------------------------------ +// form to add a category +// ------------------------------------------------------------------------ +function add_category_form($in_action) { + // initiate the object + $form = new FormValidator('note','post', api_get_self().'?action='.$in_action); + // settting the form elements + $form->addElement('header', '', get_lang('AddACategory')); + $form->addElement('text', 'category_name', get_lang('CategoryName'),array('size'=>'95')); + $form->addElement('html_editor', 'category_description', get_lang('CategoryDescription'), null, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200')); + $form->addElement('style_submit_button', 'SubmitNote', get_lang('AddTestCategory'), 'class="add"'); + // setting the rules + $form->addRule('category_name', '
    '.get_lang('ThisFieldIsRequired'), 'required'); + // The validation or display + if ($form->validate()) + { + $check = Security::check_token('post'); + if ($check) { + $values = $form->exportValues(); + $v_name = Security::remove_XSS($values['category_name'], COURSEMANAGER); + $v_description = Security::remove_XSS($values['category_description'], COURSEMANAGER); + $objcat = new Testcategory(0, $v_name, $v_description); + if ($objcat->addCategoryInBDD()) { + Display::display_confirmation_message(get_lang('AddCategoryDone')); + } + else { + Display::display_confirmation_message(get_lang('AddCategoryNameAlreadyExists')); + } + } + Security::clear_token(); + display_add_category(); + display_categories(); + } + else + { + display_goback(); + $token = Security::get_token(); + $form->addElement('hidden','sec_token'); + $form->setConstants(array('sec_token' => $token)); + $form->display(); + display_categories(); + } +} + + +// ------------------------------------------------------------------------ +// Display add category button +// ------------------------------------------------------------------------ +function display_add_category() { + echo ''; + echo "
    "; +} + + +// ------------------------------------------------------------------------ +// Display category list +// ------------------------------------------------------------------------ +function display_categories() { + $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $sql = "SELECT * FROM $t_cattable ORDER BY name"; + $res = Database::query($sql, __FILE__, __LINE__); + while ($row = Database::fetch_array($res)) { + // le titre avec le nombre de questions qui sont dans cette catégorie + $tmpobj = new Testcategory($row['id']); + $nb_question = $tmpobj->getCategoryQuestionsNumber(); + echo '
    '; + echo "".$nb_question.get_lang('NbCategory').""; + echo $row['name']; + echo '
    '; + echo '
    '; + echo $row['description']; + echo '
    '; + echo ''; + } +} + + +// ------------------------------------------------------------------------ +// display goback to category list page link +// ------------------------------------------------------------------------ +function display_goback() { + echo ''; +} + +// ------------------------------------------------------------------------ +// To allowed " in javascript dialog box without bad surprises +// replace " with two ' +// ------------------------------------------------------------------------ +function protectJSDialogQuote($in_txt) { + $res = $in_txt; + $res = str_replace("'", "\'", $res); + $res = str_replace('"', "\'\'", $res); // super astuce pour afficher les " dans les boite de dialogue + return $res; +} + +?> \ No newline at end of file diff --git a/main/inc/lib/add_course.lib.inc.php b/main/inc/lib/add_course.lib.inc.php index 7e01d1757a..93a32b9b99 100644 --- a/main/inc/lib/add_course.lib.inc.php +++ b/main/inc/lib/add_course.lib.inc.php @@ -297,6 +297,9 @@ function update_Db_course($course_db_name = null) { $TABLEQUIZQUESTIONLIST = $course_db_name . 'quiz_question'; $TABLEQUIZANSWERSLIST = $course_db_name . 'quiz_answer'; $TABLEQUIZQUESTIONOPTION = $course_db_name . 'quiz_question_option'; + + $table_quiz_question_category = $course_db_name . 'quiz_question_category'; + $table_quiz_question_rel_category = $course_db_name . 'quiz_question_rel_category'; // Dropbox $TABLETOOLDROPBOXPOST = $course_db_name . 'dropbox_post'; @@ -646,6 +649,7 @@ function update_Db_course($course_db_name = null) { session_id smallint default 0, propagate_neg INT NOT NULL DEFAULT 0, review_answers INT NOT NULL DEFAULT 0, + random_by_category INT NOT NULL DEFAULT 0, PRIMARY KEY (c_id, id) )" . $charset_clause; Database::query($sql); @@ -693,8 +697,6 @@ function update_Db_course($course_db_name = null) { )" . $charset_clause; Database::query($sql); - - // Exercise tool - answer options $sql = " CREATE TABLE `".$TABLEQUIZQUESTIONOPTION . "` ( @@ -718,7 +720,28 @@ function update_Db_course($course_db_name = null) { PRIMARY KEY (c_id, question_id,exercice_id) )" . $charset_clause; Database::query($sql); - + + + + $sql = "CREATE TABLE `".$table_quiz_question_category . "` ( + $add_to_all_tables + id int NOT NULL AUTO_INCREMENT, + name varchar(255) NOT NULL, + description text NOT NULL, + PRIMARY KEY (c_id,id) + )" . $charset_clause; + Database::query($sql); + + + $sql = "CREATE TABLE `".$table_quiz_question_rel_category . "` ( + $add_to_all_tables + question_id int NOT NULL, + category_id int NOT NULL, + PRIMARY KEY (c_id,question_id) + )" . $charset_clause; + Database::query($sql); + + /* Course description */ $sql = " diff --git a/main/inc/lib/database.constants.inc.php b/main/inc/lib/database.constants.inc.php index 1a414b1cae..205eae0181 100644 --- a/main/inc/lib/database.constants.inc.php +++ b/main/inc/lib/database.constants.inc.php @@ -15,6 +15,7 @@ */ //See #3910 defines the default prefix for the single course database +// Modified by hubert.borderiou 2011-10-21 Add course category define('DB_COURSE_PREFIX', 'c_'); // Main database tables @@ -195,6 +196,8 @@ define('TABLE_QUIZ_TEST', 'quiz'); define('TABLE_QUIZ_ANSWER', 'quiz_answer'); define('TABLE_QUIZ_TEST_QUESTION', 'quiz_rel_question'); define('TABLE_QUIZ_QUESTION_OPTION','quiz_question_option'); +define('TABLE_QUIZ_QUESTION_CATEGORY', 'quiz_question_category'); +define('TABLE_QUIZ_QUESTION_REL_CATEGORY', 'quiz_question_rel_category'); // Linked resource table //@todo table exists? diff --git a/main/inc/lib/fckeditor/toolbars/default/test_category.php b/main/inc/lib/fckeditor/toolbars/default/test_category.php new file mode 100644 index 0000000000..1ba97aa396 --- /dev/null +++ b/main/inc/lib/fckeditor/toolbars/default/test_category.php @@ -0,0 +1,10 @@ + diff --git a/main/install/migrate-db-1.8.8-1.9.0-pre.sql b/main/install/migrate-db-1.8.8-1.9.0-pre.sql index 1bc65b49ab..3406f6813a 100755 --- a/main/install/migrate-db-1.8.8-1.9.0-pre.sql +++ b/main/install/migrate-db-1.8.8-1.9.0-pre.sql @@ -128,4 +128,5 @@ INSERT INTO course_setting(variable,value,category) VALUES ('course_grading_mode ALTER TABLE quiz ADD COLUMN review_answers INT NOT NULL DEFAULT 0; ALTER TABLE student_publication ADD COLUMN contains_file INTEGER NOT NULL DEFAULT 1; ALTER TABLE student_publication ADD COLUMN allow_text_assignment INTEGER NOT NULL DEFAULT 0; +ALTER TABLE quiz ADD COLUMN random_by_category INT NOT NULL DEFAULT 0;