diff --git a/main/exercice/exercise.class.php b/main/exercice/exercise.class.php index b3f38b2c92..302d8d83ef 100644 --- a/main/exercice/exercise.class.php +++ b/main/exercice/exercise.class.php @@ -68,6 +68,8 @@ class Exercise public $categories_grouping = true; public $fastExerciseEdition = false; public $endButton = 0; + public $categoryWithQuestionList; + public $mediaList; /** * Constructor of the class @@ -111,9 +113,9 @@ class Exercise /** * Reads exercise informations from the data base * - * @author - Olivier Brouckaert - * @param - int $id - exercise ID - * @return - boolean - true if exercise exists, otherwise false + * @author Olivier Brouckaert + * @param int $id - exercise ID + * @return boolean - true if exercise exists, otherwise false */ public function read($id) { @@ -121,8 +123,8 @@ class Exercise return false; } global $_configuration; - $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST); + $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST); $table_lp_item = Database::get_course_table(TABLE_LP_ITEM); $id = intval($id); $sql = "SELECT * FROM $TBL_EXERCICES WHERE c_id = ".$this->course_id." AND iid = ".$id; @@ -180,12 +182,14 @@ class Exercise $this->start_time = $object->start_time; } - //control time + // Control time $this->expired_time = $object->expired_time; - //Checking if question_order is correctly set + // Checking if question_order is correctly set $this->questionList = $this->selectQuestionList(true); + $this->setMediaList(); + //overload questions list with recorded questions list //load questions only for exercises of type 'one question per page' //this is needed only is there is no questions @@ -386,7 +390,12 @@ class Exercise */ public function updateRandomByCat($random) { - if (in_array($random, array(EXERCISE_CATEGORY_RANDOM_SHUFFLED, EXERCISE_CATEGORY_RANDOM_ORDERED, EXERCISE_CATEGORY_RANDOM_DISABLED))) { + if (in_array($random, array( + EXERCISE_CATEGORY_RANDOM_SHUFFLED, + EXERCISE_CATEGORY_RANDOM_ORDERED, + EXERCISE_CATEGORY_RANDOM_DISABLED + ) + )) { $this->randomByCat = $random; } else { $this->randomByCat = EXERCISE_CATEGORY_RANDOM_DISABLED; @@ -451,10 +460,12 @@ class Exercise } /** - * If false the question list will be managed as always if true the question will be filtered depending of the exercise settings (table c_quiz_rel_category) + * If false the question list will be managed as always if true the question will be filtered + * depending of the exercise settings (table c_quiz_rel_category) * @param bool active or inactive grouping **/ - public function setCategoriesGrouping($status) { + public function setCategoriesGrouping($status) + { $this->categories_grouping = (bool) $status; } @@ -466,7 +477,7 @@ class Exercise * @param string $sord * @param array $where_condition */ - public function getQuestionList($start, $limit, $sidx, $sord, $where_condition = array()) + public function getQuestionListPagination($start, $limit, $sidx, $sord, $where_condition = array()) { if (!empty($this->id)) { $category_list = Testcategory::getListOfCategoriesNameForTest($this->id, false); @@ -525,110 +536,269 @@ class Exercise } /** - * returns the array with the question ID list - * - * @author - Olivier Brouckaert - * @return - array - question ID list + * Gets the question list ordered by the question_order setting (drag and drop) + * @return array */ - function selectQuestionList($from_db = false) + private function getQuestionOrderedList() { - if ($from_db && !empty($this->id)) { - $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); - $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); + $questionList = array(); - // Getting question_order count (to verify that the question list is correct and all question_order's were set) - $sql = "SELECT DISTINCT e.question_order - FROM $TBL_EXERCICE_QUESTION e INNER JOIN $TBL_QUESTIONS q - ON (e.question_id = q.iid) - WHERE e.exercice_id = ".Database::escape_string($this->id); - $result = Database::query($sql); + $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); + $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION); - $count_question_orders = Database::num_rows($result); + // Getting question_order to verify that the question list is correct and all question_order's were set + $sql = "SELECT DISTINCT e.question_order + FROM $TBL_EXERCICE_QUESTION e INNER JOIN $TBL_QUESTIONS q + ON (e.question_id = q.iid) + WHERE e.exercice_id = ".Database::escape_string($this->id); + $result = Database::query($sql); - // Getting question list from the order (question list interface drag n drop). - $sql = "SELECT e.question_id, e.question_order - FROM $TBL_EXERCICE_QUESTION e INNER JOIN $TBL_QUESTIONS q - ON (e.question_id= q.iid) - WHERE e.exercice_id = '".Database::escape_string($this->id)."' - ORDER BY question_order"; - $result = Database::query($sql); + $count_question_orders = Database::num_rows($result); + + // Getting question list from the order (question list drag n drop interface ). + $sql = "SELECT e.question_id, e.question_order + FROM $TBL_EXERCICE_QUESTION e INNER JOIN $TBL_QUESTIONS q + ON (e.question_id= q.iid) + WHERE e.exercice_id = '".Database::escape_string($this->id)."' + ORDER BY question_order"; + $result = Database::query($sql); + + // Fills the array with the question ID for this exercise + // the key of the array is the question position + $temp_question_list = array(); + + $counter = 1; + while ($new_object = Database::fetch_object($result)) { + // Correct order. + $questionList[$new_object->question_order] = $new_object->question_id; + // Just in case we save the order in other array + $temp_question_list[$counter] = $new_object->question_id; + $counter++; + } + + if (!empty($temp_question_list)) { + /* If both array don't match it means that question_order was not correctly set + for all questions using the default mysql order */ + if (count($temp_question_list) != $count_question_orders) { + $questionList = $temp_question_list; + } + } + + return $questionList; + } + + /** + * Select N values from the questions per category array + * @param array $question_list + * @param array $questions_by_category per category + * @return array + */ + private function pickQuestionsPerCategory($question_list, $questions_by_category) + { + if (!empty($questions_by_category)) { + // Sets random per category + $numberOfQuestions = $this->random; + $randomize = true; + + // If random is not set then take the max value, this value could be set to 1000 or 9999 + if ($this->random == -1 || empty($this->random)) { + $numberOfQuestions = count($question_list); + $randomize = false; + } - // Fills the array with the question ID for this exercise - // the key of the array is the question position $temp_question_list = array(); - $question_list = array(); - - $counter = 1; - while ($new_object = Database::fetch_object($result)) { - //Correct order - $question_list[$new_object->question_order] = $new_object->question_id; - //Just in case we save the order in other array - $temp_question_list[$counter] = $new_object->question_id; - $counter++; + + while (list($category_id, $categoryQuestionList) = each($questions_by_category)) { + $elements = Testcategory::getNElementsFromArray($categoryQuestionList, $numberOfQuestions, $randomize); + $temp_question_list[] = $elements; } + // Keeps the + $temp_question_list = ArrayClass::array_flatten($temp_question_list); if (!empty($temp_question_list)) { - //If both array don't match it means that question_order was not correctly set for all questions using the default mysql order - if (count($temp_question_list) != $count_question_orders) { - $question_list = $temp_question_list; - } + $question_list = $temp_question_list; } + } - if ($this->categories_grouping) { - //Selecting question list depending in categories + return $question_list; + } - $random_by_category = $this->isRandomByCat(); + /** + * Selecting question list depending in the exercise-category + * relationship (category table in exercise settings) + * + * @param $question_list + * @return array + */ + public function getQuestionListWithCategoryListFilteredByCategorySettings($question_list) + { + $result = array(); + $result['question_list'] = array(); + $result['category_with_questions_list'] = array(); - $categories_added_in_exercise = array(); + $randomByCategory = $this->isRandomByCat(); + $categoriesAddedInExercise = array(); - switch ($random_by_category) { - case EXERCISE_CATEGORY_RANDOM_SHUFFLED: - case EXERCISE_CATEGORY_RANDOM_DISABLED: - $cat = new Testcategory(); - //$categories_added_in_exercise = $this->get_categories_with_name_in_exercise(); - $categories_added_in_exercise = $cat->get_category_exercise_tree($this->id, $this->course['real_id']); - if (!empty($categories_added_in_exercise)) { - shuffle($categories_added_in_exercise); - } - break; - case EXERCISE_CATEGORY_RANDOM_ORDERED: - $cat = new Testcategory(); - $categories_added_in_exercise = $cat->get_category_exercise_tree($this->id, $this->course['real_id'], 'title DESC'); - break; + switch ($randomByCategory) { + case EXERCISE_CATEGORY_RANDOM_DISABLED: // 0 + break; + case EXERCISE_CATEGORY_RANDOM_SHUFFLED: // 1 + $cat = new Testcategory(); + $categoriesAddedInExercise = $cat->getCategoryExerciseTree($this->id, $this->course['real_id']); + + if (!empty($categoriesAddedInExercise)) { + shuffle($categoriesAddedInExercise); } + break; + case EXERCISE_CATEGORY_RANDOM_ORDERED: // 2 + $cat = new Testcategory(); + $categoriesAddedInExercise = $cat->getCategoryExerciseTree($this->id, $this->course['real_id'], 'title DESC'); + break; + } + + // Checking if the "category rel exercise" was set + $totalCategoriesRelExercise = 0; + + if (!empty($categoriesAddedInExercise)) { + foreach ($categoriesAddedInExercise as $category_info) { + $totalCategoriesRelExercise += intval($category_info['count_questions']); + } + } + + // "Category rel exercise" is empty we search now for the "category rel question" relationships + if (empty($totalCategoriesRelExercise)) { + $randomByCategory = $this->isRandomByCat(); + switch ($randomByCategory) { + case EXERCISE_CATEGORY_RANDOM_DISABLED: // 0 + // No category order to apply check the random + $question_list = $this->selectRandomList($question_list); + break; + case EXERCISE_CATEGORY_RANDOM_SHUFFLED: // 1 + // Getting questions by category in an exercise with shuffling mode ON + $questions_by_category = Testcategory::getQuestionsByCat($this->id, $question_list, null, true); + $question_list = $this->pickQuestionsPerCategory($question_list, $questions_by_category); + break; + case EXERCISE_CATEGORY_RANDOM_ORDERED: // 2 + // Getting questions by category in an exercise ordered by category title + $questions_by_category = Testcategory::getQuestionsByCat($this->id, $question_list); + $question_list = $this->pickQuestionsPerCategory($question_list, $questions_by_category); + break; + } + + } else { + // Reorder questions depending of the category settings + + if (!empty($categoriesAddedInExercise)) { + // Checking if the category rel exercise settings was set (category table in the exercise settings) + + $categories_in_questions = Testcategory::getQuestionsByCat($this->id); - if (!empty($categories_added_in_exercise)) { - $question_list_based_in_categories = array(); - $categories_in_questions = Testcategory::getQuestionsByCat($this->id); - $question_id_added_already = array(); + // Parsing question according the category rel exercise settings + $question_list_based_in_categories = array(); + $question_id_added_already = array(); - foreach ($categories_added_in_exercise as $category_info) { - $category_id = $category_info['category_id']; - if (isset($categories_in_questions[$category_id])) { - //How many question will be picked from this category - $count = $category_info['count_questions']; + foreach ($categoriesAddedInExercise as $category_info) { + $category_id = $category_info['category_id']; + if (isset($categories_in_questions[$category_id])) { + // How many question will be picked from this category. + $count = $category_info['count_questions']; - if (!empty($count)) { - //Question list for this category - $questions_for_this_category = $categories_in_questions[$category_id]; + if (!empty($count)) { + // Question list for this category - //Removing questions already added $questions_for_this_category (due multiple categories by question) - $questions_for_this_category = array_diff($questions_for_this_category, $question_id_added_already); + $questions_for_this_category = $categories_in_questions[$category_id]; - if (!empty($questions_for_this_category)) { - //Getting X number of questions for this category + // Removing questions already added $questions_for_this_category (due multiple categories by question) + $questions_for_this_category = array_diff($questions_for_this_category, $question_id_added_already); + + if (!empty($questions_for_this_category)) { + // Getting X number of questions for this category + if ($count != -1) { $question_list_for_category = array_slice($questions_for_this_category, 0, $count); - $question_list_based_in_categories[$category_id] = $question_list_for_category; - $question_id_added_already = array_merge($question_id_added_already, $question_list_for_category); + } else { + // All questions + $question_list_for_category = $questions_for_this_category; } + $question_list_based_in_categories[$category_id] = $question_list_for_category; + $question_id_added_already = array_merge($question_id_added_already, $question_list_for_category); } } } + } + if (!empty($question_list_based_in_categories)) { + $question_list = ArrayClass::array_flatten($question_list_based_in_categories); + } + } + } - if (!empty($question_list_based_in_categories)) { - $question_list = ArrayClass::array_flatten($question_list_based_in_categories); + $result['question_list'] = isset($question_list) ? $question_list : array(); + $result['category_with_questions_list'] = isset($questions_by_category) ? $questions_by_category : array(); + + + if (!empty($result['category_with_questions_list'])) { + global $app; + $em = $app['orm.em']; + $repo = $em->getRepository('Entity\CQuizCategory'); + + $newCategoryList = array(); + + foreach ($result['category_with_questions_list'] as $categoryId => $questionList) { + + $cat = new Testcategory($categoryId); + $cat = (array)$cat; + $cat['iid'] = $cat['id']; + $cat['name'] = $cat['title']; + + $categoryParentInfo = null; + + if (!empty($cat['parent_id'])) { + if (!isset($parentsLoaded[$cat['parent_id']])) { + $categoryEntity = $em->find('Entity\CQuizCategory', $cat['parent_id']); + $parentsLoaded[$cat['parent_id']] = $categoryEntity; + } else { + $categoryEntity = $parentsLoaded[$cat['parent_id']]; + } + $path = $repo->getPath($categoryEntity); + if (isset($path) && isset($path[0])) { + $categoryParentId = $path[0]->getIid(); + + $categoryParentInfo['id'] = $categoryParentId; + $categoryParentInfo['iid'] = $categoryParentId; + $categoryParentInfo['parent_path'] = null; + $categoryParentInfo['title'] = $path[0]->getTitle(); + $categoryParentInfo['name'] = $path[0]->getTitle(); + $categoryParentInfo['parent_id'] = null; } } + $cat['parent_info'] = $categoryParentInfo; + $newCategoryList[$categoryId] = array( + 'category' => $cat, + 'question_list' => $questionList + ); + } + $result['category_with_questions_list'] = $newCategoryList; + } + return $result; + } + + /** + * Returns the array with the question ID list ordered by question order, + * + * @author Olivier Brouckaert + * @param bool $from_db + * @return array question ID list + */ + public function selectQuestionList($from_db = false) + { + if ($from_db && !empty($this->id)) { + + // The question list is now ordered with the question_order parameter (normal behaviour) + $question_list = $this->getQuestionOrderedList(); + + if ($this->categories_grouping) { + $result = $this->getQuestionListWithCategoryListFilteredByCategorySettings($question_list); + $this->categoryWithQuestionList = $result['category_with_questions_list']; + $question_list = $result['question_list']; } return $question_list; } @@ -642,38 +812,39 @@ class Exercise * @author - Olivier Brouckaert * @return integer - number of questions */ - function selectNbrQuestions() + public function selectNbrQuestions() { return sizeof($this->questionList); } - function selectPropagateNeg() + public function selectPropagateNeg() { return $this->propagate_neg; } /** * Selects questions randomly in the question list + * If the exercise is not set to take questions randomly, returns the question list + * without randomizing, otherwise, returns the list with questions selected randomly * * @author Olivier Brouckaert, Modified by Hubert Borderiou 15 nov 2011 - * @param array - * @return array - if the exercise is not set to take questions randomly, returns the question list - * without randomizing, otherwise, returns the list with questions selected randomly + * @param array question list + * @return array question list modified or unmodified * */ public function selectRandomList($question_list) { $nbQuestions = $this->selectNbrQuestions(); - //Not a random exercise, or if there are not at least 2 questions + // Not a random exercise, or if there are not at least 2 questions if ($this->random == 0 || $nbQuestions < 2) { return $question_list; } + if ($nbQuestions != 0) { shuffle($question_list); $my_random_list = array_combine(range(1, $nbQuestions), $question_list); $my_question_list = array(); - // $this->random == -1 if random with all questions if ($this->random > 0) { $i = 0; foreach ($my_random_list as $item) { @@ -687,7 +858,6 @@ class Exercise } else { $my_question_list = $my_random_list; } - return $my_question_list; } } @@ -922,7 +1092,7 @@ class Exercise * * @author - Olivier Brouckaert */ - function save($type_e = '') + public function save($type_e = '') { $_course = api_get_course_info(); $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST); @@ -1039,15 +1209,15 @@ class Exercise $this->search_engine_save(); } } - $this->save_categories_in_exercise($this->categories); // Updates the question position. $this->update_question_positions(); } - /* Updates question position */ - + /** + * Updates question position + */ public function update_question_positions() { $quiz_question_table = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); @@ -1056,7 +1226,7 @@ class Exercise if (!empty($question_list) && !empty($this->course_id) && !empty($this->id)) { foreach ($question_list as $position => $questionId) { $sql = "UPDATE $quiz_question_table SET question_order ='".intval($position)."'". - "WHERE c_id = ".$this->course_id." AND question_id = ".intval($questionId)." AND exercice_id = ".$this->id; + "WHERE c_id = ".$this->course_id." AND question_id = ".intval($questionId)." AND exercice_id = ".$this->id; Database::query($sql); } } @@ -1065,11 +1235,11 @@ class Exercise /** * Adds a question into the question list * - * @author - Olivier Brouckaert - * @param - integer $questionId - question ID - * @return - boolean - true if the question has been added, otherwise false + * @author Olivier Brouckaert + * @param integer $questionId - question ID + * @return boolean - true if the question has been added, otherwise false */ - function addToList($questionId) + public function addToList($questionId) { // checks if the question ID is not in the list if (!$this->isInList($questionId)) { @@ -1147,8 +1317,6 @@ class Exercise */ public function createForm($form, $type = 'full') { - global $id; - if (empty($type)) { $type = 'full'; } @@ -1413,7 +1581,6 @@ class Exercise } // Number of random question. - $max = ($this->id > 0) ? $this->selectNbrQuestions() : 10; $option = range(0, $max); $option[0] = get_lang('No'); @@ -1447,7 +1614,7 @@ class Exercise $form->addGroup($radiocat, null, get_lang('RandomQuestionByCategory'), ''); $form->addElement('html', '
 
'); - // Category name . + // Category name. $radio_display_cat_name = array(); $radio_display_cat_name[] = $form->createElement( 'radio', @@ -1486,7 +1653,6 @@ class Exercise array('onclick' => 'activate_start_date()') ); - //$var = Exercise::selectTimeLimit(); // Start time. if (($this->start_time != '0000-00-00 00:00:00')) { $form->addElement('html', '
'); @@ -1514,14 +1680,14 @@ class Exercise $form->addElement('html', '
'); // Propagate negative values. - $diplay = 'block'; + $display = 'block'; $form->addElement('checkbox', 'propagate_neg', null, get_lang('PropagateNegativeResults')); $form->addElement('html', '
 
'); $form->addElement('checkbox', 'review_answers', null, get_lang('ReviewAnswers')); - $form->addElement('html', '
'); + $form->addElement('html', '
'); - // Timer control. + // Exercise timer. $form->addElement( 'checkbox', 'enabletimercontrol', @@ -1604,7 +1770,6 @@ class Exercise // Category selection. $cat = new Testcategory(); - $cat_form = $cat->return_category_form($this); $form->addElement('html', $cat_form); @@ -1756,7 +1921,7 @@ class Exercise $this->save($type); } - function search_engine_save() + public function search_engine_save() { if ($_POST['index_document'] != 1) { return; @@ -2163,7 +2328,8 @@ class Exercise * Copy exercise categories to a new exercise * @params obj exercise object */ - function copy_exercise_categories($new_exercise_obj) { + function copy_exercise_categories($new_exercise_obj) + { $categories = $this->get_categories_in_exercise(); if ($categories) { $cat_list = array(); @@ -2654,7 +2820,7 @@ class Exercise unset($objQuestionTmp); // Construction of the Answer object - $objAnswerTmp = new Answer($questionId); + $objAnswerTmp = new Answer($questionId, null, $this); $nbrAnswers = $objAnswerTmp->selectNbrAnswers(); if ($debug) { @@ -3872,7 +4038,6 @@ class Exercise //Fixes multiple answer question in order to be exact if ($answerType == MULTIPLE_ANSWER || $answerType == GLOBAL_MULTIPLE_ANSWER) { $diff = @array_diff($answer_correct_array, $real_answers); - //var_dump($diff); /* * All good answers or nothing works like exact $counter = 1; @@ -4586,6 +4751,7 @@ class Exercise /** * Returns an array with the media list + * @param array question list * @example there's 1 question with iid 5 that belongs to the media question with iid = 100 * * array (size=2) @@ -4600,15 +4766,15 @@ class Exercise * * @return array */ - function get_media_list() + function setMediaList() { $media_questions = array(); - //$question_list = $this->get_validated_question_list(); - $question_list = $this->selectQuestionList(true); + $question_list = $this->questionList; if (!empty($question_list)) { foreach ($question_list as $questionId) { $objQuestionTmp = Question::read($questionId); + // If a media question exists if (isset($objQuestionTmp->parent_id) && $objQuestionTmp->parent_id != 0) { $media_questions[$objQuestionTmp->parent_id][] = $objQuestionTmp->id; @@ -4618,23 +4784,28 @@ class Exercise } } } + $this->mediaList = $media_questions; + } - return $media_questions; + public function getMediaList() + { + return $this->mediaList; } /** - * @param array $media_list + *Is media question activated * @return bool */ - function media_is_activated($media_list) + public function media_is_activated() { + $mediaQuestions = $this->getMediaList(); $active = false; - if (isset($media_list) && !empty($media_list)) { - $media_count = count($media_list); + if (isset($mediaQuestions) && !empty($mediaQuestions)) { + $media_count = count($mediaQuestions); if ($media_count > 1) { return true; } elseif ($media_count == 1) { - if (isset($media_list[999])) { + if (isset($mediaQuestions[999])) { return false; } else { return true; @@ -4645,199 +4816,17 @@ class Exercise return $active; } - /** - * @deprecated - * @return array - */ - function get_validated_question_list_2() - { - $question_list = array(); - $is_random_by_category = $this->isRandomByCat(); - - if ($is_random_by_category == 0) { - if ($this->isRandom()) { - $question_list = $this->selectRandomList(); - } else { - $question_list = $this->selectQuestionList(); - } - } else { - if ($this->isRandom()) { - - // USE question categories - - /* Get questions by category for this exercice - we have to choice $objExercise->random question in each array values of $questions_in_category - key of $tabCategoryQuestions are the categopy id (0 for not in a category) - value is the array of question id of this category - */ - $temp_question_list = array(); - - //Getting questions by category - $questions_in_category = 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) { - $questions_in_category = Testcategory::sortTabByBracketLabel($questions_in_category); - }*/ - - $number_of_random_question = $this->random; - if ($this->random == -1) { - $number_of_random_question = count($this->questionList); - } - - //Only 1 question can have a category - if (!empty($questions_in_category)) { - $one_question_per_category = array(); - $questions_added = array(); - foreach ($questions_in_category as $category_id => $question_list) { - foreach ($question_list as $question_id) { - if (!in_array($question_id, $questions_added)) { - $one_question_per_category[$category_id][] = $question_id; - $questions_added[] = $question_id; - } - } - } - $questions_in_category = $one_question_per_category; - } - - while (list($category_id, $question_id) = each($questions_in_category)) { - $elements = Testcategory::getNElementsFromArray($question_id, $number_of_random_question); - $temp_question_list = array_merge($temp_question_list, $elements); - } - - // shuffle the question list if test is not grouped by categories - if ($isRandomByCategory == 1) { - shuffle($temp_question_list); // or not - } - $question_list = $temp_question_list; - } else { - // Problem, random by category has been selected and we have no $this->isRandom nnumber of question selected - // Should not happened - } - } - - return $question_list; - } - - /** - * Get list of questions depending of the category random settings, exercise random settings, and - * exercise categories settings - */ - function get_validated_question_list() - { - // Getting current question list - $question_list = $this->selectQuestionList(true); - - // Getting random by category setting - $random_by_category = $this->isRandomByCat(); - - switch ($random_by_category) { - case EXERCISE_CATEGORY_RANDOM_SHUFFLED: - // Randomized array - if ($this->isRandom()) { - $question_list = $this->selectRandomList($question_list); - } - break; - case EXERCISE_CATEGORY_RANDOM_DISABLED: - // Randomized array - /*if ($this->isRandom()) { - $question_list = $this->selectRandomList($question_list); - }*/ - break; - case EXERCISE_CATEGORY_RANDOM_ORDERED: - - if (!$this->isRandom()) { - //break; - } - - /** - * Get questions by category for this exercise - * we have to choice $objExercise->random question in each array values of $questions_by_category - * key of $tabCategoryQuestions are the category id (0 for not in a category) - * value is the array of question id of this category - */ - - // Getting questions by category. - $questions_by_category = Testcategory::getQuestionsByCat($this->id, $question_list); - - /** - * The order is based in the category in this case [biology] is first that [maths] - - * Example: - * [biology] Question 1 - * [biology] Question 2 - * [biology] Question 3 - * [maths] Question 1 - * [maths] Question 2 - */ - - // If test option is Grouped By Categories - //if ($random_by_category == EXERCISE_CATEGORY_RANDOM_ORDERED) { - //$questions_by_category = Testcategory::sortCategoriesQuestionByName($questions_by_category); - //} - - $number_of_random_question = $this->random; - if ($this->random == -1 || empty($this->random)) { - $number_of_random_question = count($question_list); - } - - // Only 1 question per category - /* - if (!empty($questions_by_category)) { - $one_question_per_category = array(); - $questions_added = array(); - foreach ($questions_by_category as $category_id => $question_list) { - foreach ($question_list as $question_id) { - if (!in_array($question_id, $questions_added)) { - $one_question_per_category[$category_id][] = $question_id; - $questions_added[] = $question_id; - } - } - } - $questions_by_category = $one_question_per_category; - }*/ - - $temp_question_list = array(); - while (list($category_id, $question_list) = each($questions_by_category)) { - $elements = Testcategory::getNElementsFromArray($question_list, $number_of_random_question); - $temp_question_list = array_merge($temp_question_list, $elements); - } - - // shuffle the question list if test is not grouped by categories - //if ($random_by_category == EXERCISE_CATEGORY_RANDOM_SHUFFLED) { - //shuffle($temp_question_list); - //} - $question_list = $temp_question_list; - break; - } - return $question_list; - } - - /** * Gets question list from the exercise - * @params bool expand or not question list (true show all questions, false show media question id instead of the question ids) + * @params bool Expand or not question list + * (true show all questions, false show media question id instead of the question ids) + * @return array unflatten question list (no medias) */ - function get_question_list($expand_media_questions = false) + public function getQuestionList($expand_media_questions = false) { - $question_list = $this->get_validated_question_list(); - $question_list = $this->transform_question_list_with_medias($question_list, $expand_media_questions); - return $question_list; + $questionList = $this->selectQuestionList(); + $questionList = $this->transform_question_list_with_medias($questionList, $expand_media_questions); + return $questionList; } /** @@ -4850,7 +4839,8 @@ class Exercise { $new_question_list = array(); if (!empty($question_list)) { - $media_questions = $this->get_media_list(); + $media_questions = $this->getMediaList(); + $media_active = $this->media_is_activated($media_questions); if ($media_active) { @@ -5040,7 +5030,7 @@ class Exercise { //Real question count $question_count = 0; - $question_list = $this->get_question_list(); + $question_list = $this->getQuestionList(); if (!empty($question_list)) { $question_count = count($question_list); } @@ -5071,7 +5061,8 @@ class Exercise /** * @return bool */ - function get_categories_in_exercise() { + public function get_categories_in_exercise() + { $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY); if (!empty($this->id)) { $sql = "SELECT * FROM $table WHERE exercise_id = {$this->id} AND c_id = {$this->course_id} "; @@ -5094,8 +5085,9 @@ class Exercise public function get_categories_with_name_in_exercise($order = null) { $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY); - $table_category = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); - $sql = "SELECT * FROM $table qc INNER JOIN $table_category c ON (category_id = c.iid) WHERE exercise_id = {$this->id} AND qc.c_id = {$this->course_id} "; + $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY); + $sql = "SELECT * FROM $table qc INNER JOIN $table_category c ON (category_id = c.iid) + WHERE exercise_id = {$this->id} AND qc.c_id = {$this->course_id} "; if (!empty($order)) { $sql .= "ORDER BY $order "; } @@ -5112,11 +5104,12 @@ class Exercise /** * Get total number of question that will be parsed when using the category/exercise */ - function getNumberQuestionExerciseCategory() + public function getNumberQuestionExerciseCategory() { $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY); if (!empty($this->id)) { - $sql = "SELECT SUM(count_questions) count_questions FROM $table WHERE exercise_id = {$this->id} AND c_id = {$this->course_id}"; + $sql = "SELECT SUM(count_questions) count_questions FROM $table + WHERE exercise_id = {$this->id} AND c_id = {$this->course_id}"; $result = Database::query($sql); if (Database::num_rows($result)) { $row = Database::fetch_array($result); @@ -5127,13 +5120,15 @@ class Exercise } /** + * Save categories in the TABLE_QUIZ_REL_CATEGORY table * @param array $categories */ - function save_categories_in_exercise($categories) + public function save_categories_in_exercise($categories) { if (!empty($categories) && !empty($this->id)) { $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY); $sql = "DELETE FROM $table WHERE exercise_id = {$this->id} AND c_id = {$this->course_id}"; + error_log($sql); Database::query($sql); if (!empty($categories)) { foreach ($categories as $category_id => $count_questions) { @@ -5184,23 +5179,24 @@ class Exercise * @param int $current_question * @return string */ - public function getProgressPagination($exe_id, $questionList, $my_remind_list, $reminder, $remind_question_id, $questionListFlatten, $mediaQuestions, $url, $current_question) + public function getProgressPagination($exe_id, $questionList, $questionListFlatten, $remindList, $reminder, $remindQuestionId, $url, $current_question) { + $mediaQuestions = $this->getMediaList(); $exercise_result = get_answered_questions_from_attempt($exe_id, $this); $fixedRemindList = array(); - if (!empty($my_remind_list)) { - foreach ($questionList as $questionId) { - if (in_array($questionId, $my_remind_list)) { + if (!empty($remindList)) { + foreach ($questionListFlatten as $questionId) { + if (in_array($questionId, $remindList)) { $fixedRemindList[] = $questionId; } } } if (isset($reminder) && $reminder == 2) { - $values = array_flip($questionList); + $values = array_flip($questionListFlatten); if (!empty($current_question)) { - $current_question = isset($values[$remind_question_id]) ? $values[$remind_question_id] + 1 : $values[$fixedRemindList[0]] +1; + $current_question = isset($values[$remindQuestionId]) ? $values[$remindQuestionId] + 1 : $values[$fixedRemindList[0]] +1; } } @@ -5208,10 +5204,13 @@ class Exercise $categoryList = null; if (empty($categoryList)) { - $categoryList = Testcategory::getListOfCategoriesWithQuestionForTestObject($this, $questionListFlatten, $mediaQuestions); + $categoryList = $this->getListOfCategoriesWithQuestionForTest($mediaQuestions); + //var_dump($categoryList); Session::write('categoryList', $categoryList); } + //var_dump($categoryList); + $html = '
'; $html .= '
'; @@ -5229,18 +5228,95 @@ class Exercise $conditions = array(); $conditions[] = array("class" => 'answered', 'items' => $exercise_result); - $conditions[] = array("class" => 'remind', 'mode' => 'overwrite', 'items' => $my_remind_list); + $conditions[] = array("class" => 'remind', 'mode' => 'overwrite', 'items' => $remindList); $link = $url.'&num='; $html .= '
'; if (!empty($categoryList)) { - $html .= Display::progress_pagination_bar_with_categories($questionList, $categoryList, $current_question, $conditions, $link); + $html .= Display::progress_pagination_bar_with_categories($questionListFlatten, $categoryList, $current_question, $conditions, $link); } else { - $html .= Display::progress_pagination_bar($questionList, $current_question, $conditions, $link); + $html .= Display::progress_pagination_bar($questionListFlatten, $current_question, $conditions, $link); } $html .= '
'; $html .= '
'; return $html; } + + + /** + * @param array media question array + * @return array question list (flatten not grouped by Medias) + */ + public function getListOfCategoriesWithQuestionForTest($mediaQuestions) + { + $newMediaList = array(); + foreach ($mediaQuestions as $mediaId => $questionMediaList) { + foreach ($questionMediaList as $questionId) { + $newMediaList[$questionId] = $mediaId; + } + } + $categoryList = $this->categoryWithQuestionList; + $categoriesWithQuestion = array(); + foreach ($categoryList as $categoryId => $category) { + $categoriesWithQuestion[$categoryId] = $category['category']; + $categoriesWithQuestion[$categoryId]['question_list'] = $category['question_list']; + + if (!empty($newMediaList)) { + foreach ($category['question_list'] as $questionId) { + if (isset($newMediaList[$questionId])) { + $categoriesWithQuestion[$categoryId]['media_question'] = $newMediaList[$questionId]; + } else { + $categoriesWithQuestion[$categoryId]['media_question'] = 999; + } + } + } + } + return $categoriesWithQuestion; + + + foreach ($questionList as $question_id) { + $categoryList = Testcategory::getCategoryForQuestion($question_id); + + foreach ($categoryList as $categoryId) { + if (!isset($categoriesWithQuestion[$categoryId])) { + $cat = new Testcategory($categoryId); + $cat = (array)$cat; + $cat['iid'] = $cat['id']; + $cat['name'] = $cat['title']; + + if (!empty($cat['parent_id'])) { + if (!isset($parentsLoaded[$cat['parent_id']])) { + $categoryEntity = $em->find('Entity\CQuizCategory', $cat['parent_id']); + $parentsLoaded[$cat['parent_id']] = $categoryEntity; + } else { + $categoryEntity = $parentsLoaded[$cat['parent_id']]; + } + $path = $repo->getPath($categoryEntity); + + if (isset($path) && isset($path[0])) { + $categoryId = $path[0]->getIid(); + $cat['id'] = $categoryId; + $cat['iid'] = $categoryId; + $cat['parent_path'] = null; + $cat['title'] = $path[0]->getTitle(); + $cat['name'] = $path[0]->getTitle(); + $cat['parent_id'] = null; + } + $temp = isset($categoriesWithQuestion[$categoryId]) ? $categoriesWithQuestion[$categoryId]['question_list'] : array(); + $categoriesWithQuestion[$categoryId] = $cat; + $categoriesWithQuestion[$categoryId]['question_list'] = $temp; + $categoriesWithQuestion[$categoryId]['media_question'] = isset($newMediaList[$question_id]) ? $newMediaList[$question_id] : 999; + } else { + $categoriesWithQuestion[$categoryId] = $cat; + $categoriesWithQuestion[$categoryId]['media_question'] = isset($newMediaList[$question_id]) ? $newMediaList[$question_id] : 999; + } + } + + $categoriesWithQuestion[$categoryId]['question_list'][] = (int)$question_id; + } + } + return $categoriesWithQuestion; + } + } diff --git a/main/exercice/exercise_reminder.php b/main/exercice/exercise_reminder.php index 1b4aafc3dc..261b206447 100644 --- a/main/exercice/exercise_reminder.php +++ b/main/exercice/exercise_reminder.php @@ -255,18 +255,18 @@ $exercise_actions = Display::url(get_lang('EndTest'), 'javascript://', array('on $questionList = explode(',', $exercise_stat_info['data_tracking']); $questionListFlatten = $objExercise->transform_question_list_with_medias($questionList, true); -$mediaQuestions = $objExercise->get_media_list(); +$mediaQuestions = $objExercise->getMediaList($questionList); $params = "exe_id=$exe_id&exerciseId=$exerciseId&origin=$origin&learnpath_id=$learnpath_id&learnpath_item_id=$learnpath_item_id&learnpath_item_view_id=$learnpath_item_view_id&".api_get_cidreq(); $url = api_get_path(WEB_CODE_PATH).'exercice/exercise_submit.php?'.$params; -echo $objExercise->getProgressPagination($exe_id, +echo $objExercise->getProgressPagination( + $exe_id, $questionList, + $questionListFlatten, $remind_list, 2, null, - $questionListFlatten, - $mediaQuestions, $url, null ); diff --git a/main/exercice/exercise_submit.php b/main/exercice/exercise_submit.php index a8a5aea8f2..5b75143249 100644 --- a/main/exercice/exercise_submit.php +++ b/main/exercice/exercise_submit.php @@ -13,8 +13,6 @@ * When the user has answered all questions and clicks on the button "Ok", * it goes to exercise_result.php * -* Notice : This script is also used to show a question before modifying it by -* the administrator * @package chamilo.exercise * @author Olivier Brouckaert * @author Julio Montoya @@ -22,6 +20,7 @@ * Cleaning exercises (2010), * Adding hotspot delineation support (2011) * Adding reminder + ajax support (2011) + * Adding adding medias, local and global categories (2013) * Modified by hubert.borderiou (2011-10-21 question category) */ /** @@ -55,10 +54,10 @@ if (api_get_setting('show_glossary_in_extra_tools') == 'true') { $htmlHeadXtra[] = api_get_js('glossary.js'); //Glossary $htmlHeadXtra[] = api_get_js('jquery. highlight.js'); //highlight } - +// Matching question $htmlHeadXtra[] = api_get_js('jquery.jsPlumb.all.js'); -//This library is necessary for the time control feature +// This library is necessary for the time control feature $htmlHeadXtra[]= api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/epiclock/stylesheet/jquery.epiclock.css'); $htmlHeadXtra[]= api_get_css(api_get_path(WEB_LIBRARY_PATH).'javascript/epiclock/renderers/minute/epiclock.minute.css'); $htmlHeadXtra[]= api_get_js('epiclock/javascript/jquery.dateformat.min.js'); @@ -77,9 +76,6 @@ function deleteItem($item, $insertHere) { } $item.fadeOut(function() { - /*var $list = $( "ul", $trash ).length ? - $( "ul", $trash ) : - $( "
    " ).appendTo( $trash );*/ $list = $( "
    " ).appendTo($insertHere); $item.find( "a.ui-icon-trash" ).remove(); @@ -120,18 +116,7 @@ $(function() { $trash.droppable({ accept: ".drag_question > li", hoverClass: "ui-state-active", - //activeClass: "ui-state-highlight", drop: function(event, ui) { - /* - var dropped = ui.draggable; - var droppedId = dropped.attr("id"); - - var droppedOn = $(this); - var droppedOnId = droppedOn.attr("id"); - - $(this).html(dropped.html()); - $( this ).addClass("ui-state-highlight"); - */ deleteItem(ui.draggable, $(this)); } }); @@ -179,7 +164,6 @@ $(function() { } return false; }); - }); // Matching js script in order to use jsplumb @@ -290,25 +274,6 @@ var connectorType = "Straight"; jsPlumbDemo.attachBehaviour = function() { if (!_initialised) { - /*$(".hide").click(function() { - jsPlumb.toggle($(this).attr("rel")); - }); - - $(".drag").click(function() { - var s = jsPlumb.toggleDraggable($(this).attr("rel")); - $(this).html(s ? "disable dragging" : "enable dragging"); - if (!s) $("#" + $(this).attr("rel")).addClass("drag-locked"); else $("#" + $(this).attr("rel")).removeClass("drag-locked"); - $("#" + $(this).attr("rel")).css("cursor", s ? "pointer" : "default"); - }); - - $(".detach").click(function() { - jsPlumb.detachAllConnections($(this).attr("rel")); - }); - - $("#clear").click(function() { - jsPlumb.detachEveryConnection(); jsPlumbDemo.showConnectionInfo(""); - });*/ - _initialised = true; } }; @@ -363,7 +328,7 @@ $current_question = isset($_REQUEST['num']) ? intval($_REQUEST['num']) : n $error = ''; /* Teacher takes an exam and want to see a preview, we delete the objExercise from the session in order to get the latest changes in the exercise */ -if (api_is_allowed_to_edit(null,true) && isset($_GET['preview']) && $_GET['preview'] == 1 ) { +if (api_is_allowed_to_edit(null,true) && isset($_GET['preview']) && $_GET['preview'] == 1) { Session::erase('objExercise'); } @@ -377,16 +342,18 @@ if (!isset($_SESSION['objExercise']) || $_SESSION['objExercise']->id != $_REQUES // if the specified exercise doesn't exist or is disabled if (!$objExercise->read($exerciseId) || (!$objExercise->selectStatus() && !$is_allowedToEdit && ($origin != 'learnpath'))) { - if ($debug) {error_log('1.1. Error while reading the exercise'); }; + if ($debug) { error_log('1.1. Error while reading the exercise'); }; unset ($objExercise); $error = get_lang('ExerciseNotFound'); } else { // Saves the object into the session - Session::write('objExercise',$objExercise); - if ($debug) {error_log('1.1. $_SESSION[objExercise] was unset - set now - end'); }; + Session::write('objExercise', $objExercise); + if ($debug) { error_log('1.1. $_SESSION[objExercise] was unset - set now - end'); }; } } +// $objExercise = new Exercise(); $objExercise->read($exerciseId); + //2. Checking if $objExercise is set if (!isset($objExercise) && isset($_SESSION['objExercise'])) { if ($debug) { error_log('2. Loading $objExercise from session'); }; @@ -414,18 +381,18 @@ $my_remind_list = array(); $time_control = false; if ($objExercise->expired_time != 0) { - $time_control = true; + $time_control = true; } //Generating the time control key for the user $current_expired_time_key = ExerciseLib::get_time_control_key($objExercise->id, $learnpath_id, $learnpath_item_id); -if ($debug) error_log("4. current_expired_time_key: $current_expired_time_key "); +if ($debug) error_log("4. current_expired_time_key: $current_expired_time_key "); $_SESSION['duration_time'][$current_expired_time_key] = $current_timestamp; if ($time_control) { //Get the expired time of the current exercice in track_e_exercices - $total_seconds = $objExercise->expired_time*60; + $total_seconds = $objExercise->expired_time * 60; } $show_clock = true; @@ -486,18 +453,16 @@ if ($objExercise->selectAttempts() > 0) { } } -//5. Getting user exercise info (if the user took the exam before) - generating exe_id +// 5. Getting user exercise info (if the user took the exam before) - generating exe_id $exercise_stat_info = $objExercise->get_stat_track_exercise_info($learnpath_id, $learnpath_item_id, $learnpath_item_view_id); -//Media questions -$mediaQuestions = $objExercise->get_media_list(); -$media_is_activated = $objExercise->media_is_activated($mediaQuestions); - -//In LP's is enabled the "remember question" feature? - +//if (1) { if (!isset($_SESSION['questionList'])) { // Selects the list of question ID - $questionList = $objExercise->get_question_list(false); + $questionList = $objExercise->getQuestionList(); + + // Media questions. + $media_is_activated = $objExercise->media_is_activated(); //Getting order from random if ($media_is_activated == false && $objExercise->isRandom() && isset($exercise_stat_info) && !empty($exercise_stat_info['data_tracking'])) { @@ -511,8 +476,11 @@ if (!isset($_SESSION['questionList'])) { } } +//var_dump($questionList); //Fix in order to get the correct question list $questionListFlatten = $objExercise->transform_question_list_with_medias($questionList, true); +//var_dump($questionListFlatten); + Session::write('question_list_flatten', $questionListFlatten); $clock_expired_time = null; @@ -636,7 +604,6 @@ $exercise_title = $objExercise->selectTitle(); $exercise_sound = $objExercise->selectSound(); if ($debug) error_log('8. Question list loaded '.print_r($questionList, 1)); -if ($debug) error_log('8.1. Media list loaded '.print_r($mediaQuestions, 1)); $question_count = $objExercise->get_count_question_list(); @@ -649,7 +616,7 @@ if ($formSent && isset($_POST)) { $exerciseResultCoordinates = array(); } - //Only for hotspot + // Only for hotspot if (!isset($choice) && isset($_REQUEST['hidden_hotspot_id'])) { $hotspot_id = (int)($_REQUEST['hidden_hotspot_id']); $choice = array($hotspot_id => ''); @@ -680,7 +647,6 @@ if ($formSent && isset($_POST)) { $exerciseResult[$key] = $choice[$key]; //saving each question if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_DIRECT) { - //$nro_question = $current_question; // - 1; $questionId = $key; // gets the student choice for this question $choice = $exerciseResult[$questionId]; @@ -857,16 +823,15 @@ if (api_is_course_admin() && $origin != 'learnpath') { } echo '
    '; } - +//var_dump($questionList);var_dump($questionListFlatten); if ($objExercise->type == ONE_PER_PAGE) { echo $objExercise->getProgressPagination( $exe_id, $questionList, + $questionListFlatten, $my_remind_list, $reminder, $remind_question_id, - $questionListFlatten, - $mediaQuestions, api_get_self().'?'.$params, $current_question ); @@ -956,7 +921,8 @@ if ($reminder == 2) { $data_tracking = $exercise_stat_info['data_tracking']; $data_tracking = explode(',', $data_tracking); - $current_question = 1; //set by default the 1st question + // Set by default the 1st question + $current_question = 1; if (!empty($my_remind_list)) { //Checking which questions we are going to call from the remind list @@ -1011,14 +977,13 @@ if (!empty($error)) { if (!empty($exercise_sound)) { echo "", ", get_lang('Sound') . "; } + // Get number of hotspot questions for javascript validation $number_of_hotspot_questions = 0; $onsubmit = ''; $i = 0; - if (!empty($questionList)) { foreach ($questionList as $questionId) { - $i++; $objQuestionTmp = Question::read($questionId); // for sequential exercises if ($objExercise->type == ONE_PER_PAGE) { @@ -1036,9 +1001,9 @@ if (!empty($error)) { $number_of_hotspot_questions++; } } + $i++; } } - if ($number_of_hotspot_questions > 0) { $onsubmit = "onsubmit=\"return validateFlashVar('" . $number_of_hotspot_questions . "', '" . get_lang('HotspotValidateError1') . "', '" . get_lang('HotspotValidateError2') . "');\""; } @@ -1073,7 +1038,6 @@ if (!empty($error)) { $.each(question_list, function(key, question_id) { save_now(question_id, null, false); }); - var url = ""; if ('.$reminder.' == 1 ) { url = "exercise_reminder.php?'.$params.'&num='.$current_question.'"; @@ -1157,7 +1121,7 @@ if (!empty($error)) { error: function() { $("#save_for_now_"+question_id).html("'.addslashes(Display::return_icon('error.png', get_lang('Error'), array(), ICON_SIZE_SMALL)).'"); } - }); + }); return false; } @@ -1241,12 +1205,11 @@ if (!empty($error)) { $remind_list = explode(',', $exercise_stat_info['questions_to_check']); } - ExerciseLib::render_question_list($objExercise, $questionList, $current_question, $exerciseResult, $attempt_list, $remind_list, $mediaQuestions); + ExerciseLib::render_question_list($objExercise, $questionListFlatten, $questionList, $current_question, $exerciseResult, $attempt_list, $remind_list); echo ''; } - if ($origin != 'learnpath') { //so we are not in learnpath tool echo '
'; //End glossary div diff --git a/main/exercice/question.class.php b/main/exercice/question.class.php index ca28f67bf3..bd2c079fc7 100644 --- a/main/exercice/question.class.php +++ b/main/exercice/question.class.php @@ -1351,8 +1351,6 @@ abstract class Question $("#parent_id option:selected").each(function() { var questionId = $(this).val(); if (questionId != 0) { - //console.log(counter); - //console.log(questionId); if (counter >= 1) { alert("'.addslashes(get_lang('YouCantAddAnotherCategory')).'"); $("#category_id").trigger("removeItem",[{ "value" : id}]); @@ -1369,7 +1367,7 @@ abstract class Question if (return_value == 0 ) { alert("'.addslashes(get_lang('CategoryDoesNotExists')).'"); // Deleting select option tag - // $("#parent_id").find("option").remove(); + $("#category_id").find("option").remove(); $(".holder li").each(function () { if ($(this).attr("rel") == id) { @@ -1727,11 +1725,7 @@ abstract class Question public static function updateQuestionOption($id, $params, $course_id) { $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $result = Database::update( - $TBL_EXERCICE_QUESTION_OPTION, - $params, - array('c_id = ? AND id = ?' => array($course_id, $id)) - ); + $result = Database::update($TBL_EXERCICE_QUESTION_OPTION, $params, array('c_id = ? AND id = ?' => array($course_id, $id))); return $result; } @@ -1739,11 +1733,9 @@ abstract class Question public static function readQuestionOption($question_id, $course_id) { $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $result = Database::select( - '*', - $TBL_EXERCICE_QUESTION_OPTION, - array( - 'where' => array('c_id = ? AND question_id = ?' => array($course_id, $question_id)), + $result = Database::select('*', $TBL_EXERCICE_QUESTION_OPTION, array( + 'where' => array( + 'c_id = ? AND question_id = ?' => array($course_id, $question_id)), 'order' => 'iid ASC' ) ); @@ -1762,9 +1754,10 @@ abstract class Question /** * Shows question title an description * - * @param type $feedback_type - * @param type $counter + * @param int $feedback_type + * @param int $counter * @param type $score + * @param bool $show_media * * @return string */ @@ -2072,7 +2065,7 @@ abstract class Question ), 'question_category_id' => array( 'innerjoin' => " INNER JOIN ".Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY)." as quiz_rel_cat ON (quiz_rel_cat.question_id = s.iid) - INNER JOIN ".Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY)." as cat ON (cat.iid = quiz_rel_cat.category_id) + INNER JOIN ".Database::get_course_table(TABLE_QUIZ_CATEGORY)." as cat ON (cat.iid = quiz_rel_cat.category_id) ", 'where' => 'quiz_rel_cat.category_id', 'inject_fields' => 'cat.title as question_category_id, ', diff --git a/main/exercice/stats.php b/main/exercice/stats.php index 0d319f660a..c381b852ef 100644 --- a/main/exercice/stats.php +++ b/main/exercice/stats.php @@ -26,7 +26,7 @@ if (empty($session_id)) { } $count_students = count($students); -$question_list = $objExercise->get_validated_question_list(); +$question_list = $objExercise->selectQuestionList(); $data = array(); //Question title # of students who tool it Lowest score Average Highest score Maximum score diff --git a/main/exercice/testcategory.class.php b/main/exercice/testcategory.class.php index 9354f2fec8..974a959d88 100644 --- a/main/exercice/testcategory.class.php +++ b/main/exercice/testcategory.class.php @@ -70,7 +70,7 @@ class Testcategory */ public function getCategory($id) { - $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $t_cattable = Database::get_course_table(TABLE_QUIZ_CATEGORY); $id = Database::escape_string($id); $sql = "SELECT * FROM $t_cattable WHERE iid = $id "; $res = Database::query($sql); @@ -93,7 +93,7 @@ class Testcategory */ public function addCategoryInBDD() { - $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $t_cattable = Database :: get_course_table(TABLE_QUIZ_CATEGORY); $v_name = Database::escape_string($this->name); $parent_id = intval($this->parent_id); $course_id = $this->course_id; @@ -222,7 +222,7 @@ class Testcategory */ public function get_category_by_title($title , $course_id = 0) { - $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $table = Database::get_course_table(TABLE_QUIZ_CATEGORY); $course_id = intval($course_id); $title = Database::escape_string($title); @@ -248,7 +248,7 @@ class Testcategory if (empty($tag)) { return false; } - $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $table = Database::get_course_table(TABLE_QUIZ_CATEGORY); $sql = "SELECT iid, title, c_id FROM $table WHERE 1=1 "; $tag = Database::escape_string($tag); @@ -317,7 +317,7 @@ class Testcategory public static function getCategoryListInfo($in_field = "", $courseId = null) { $courseId = intval($courseId); - $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $t_cattable = Database :: get_course_table(TABLE_QUIZ_CATEGORY); $in_field = Database::escape_string($in_field); $tabres = array(); if ($in_field=="") { @@ -372,7 +372,7 @@ class Testcategory $courseId = intval($courseId); $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); - $table_category = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY); $question_id = Database::escape_string($question_id); $sql = "SELECT * FROM $t_cattable qc INNER JOIN $table_category c ON (category_id = c.iid) WHERE question_id = '$question_id' AND qc.c_id = $courseId"; $res = Database::query($sql); @@ -397,7 +397,7 @@ class Testcategory $course_id = api_get_course_int_id(); } $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); - $table_category = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY); $question_id = intval($question_id); $course_id = intval($course_id); @@ -449,7 +449,7 @@ class Testcategory $course_id = intval($course_id); $result = array(); - $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $t_cattable = Database::get_course_table(TABLE_QUIZ_CATEGORY); $catid = Database::escape_string($catid); $sql = "SELECT title FROM $t_cattable WHERE iid = '$catid' AND c_id = $course_id"; $res = Database::query($sql); @@ -507,68 +507,6 @@ class Testcategory return $categories_in_exercise; } - /** - * @param Exercise $exercise_obj - * @return array question list (flatten not grouped by Medias) - */ - public static function getListOfCategoriesWithQuestionForTestObject($exercise_obj, $questionList, $mediaQuestions) - { - $categoriesWithQuestion = array(); - $parentsLoaded = array(); - global $app; - $em = $app['orm.em']; - $repo = $em->getRepository('Entity\CQuizCategory'); - - $newMediaList = array(); - foreach ($mediaQuestions as $mediaId => $questionMediaList) { - foreach ($questionMediaList as $questionId) { - $newMediaList[$questionId] = $mediaId; - } - } - - foreach ($questionList as $question_id) { - $categoryList = Testcategory::getCategoryForQuestion($question_id); - - foreach ($categoryList as $categoryId) { - if (!isset($categoriesWithQuestion[$categoryId])) { - $cat = new Testcategory($categoryId); - $cat = (array)$cat; - $cat['iid'] = $cat['id']; - $cat['name'] = $cat['title']; - - if (!empty($cat['parent_id'])) { - if (!isset($parentsLoaded[$cat['parent_id']])) { - $categoryEntity = $em->find('Entity\CQuizCategory', $cat['parent_id']); - $parentsLoaded[$cat['parent_id']] = $categoryEntity; - } else { - $categoryEntity = $parentsLoaded[$cat['parent_id']]; - } - $path = $repo->getPath($categoryEntity); - - if (isset($path) && isset($path[0])) { - $categoryId = $path[0]->getIid(); - $cat['id'] = $categoryId; - $cat['iid'] = $categoryId; - $cat['parent_path'] = null; - $cat['title'] = $path[0]->getTitle(); - $cat['name'] = $path[0]->getTitle(); - $cat['parent_id'] = null; - } - $temp = isset($categoriesWithQuestion[$categoryId]) ? $categoriesWithQuestion[$categoryId]['question_list'] : array(); - $categoriesWithQuestion[$categoryId] = $cat; - $categoriesWithQuestion[$categoryId]['question_list'] = $temp; - $categoriesWithQuestion[$categoryId]['media_question'] = isset($newMediaList[$question_id]) ? $newMediaList[$question_id] : 999; - } else { - $categoriesWithQuestion[$categoryId] = $cat; - $categoriesWithQuestion[$categoryId]['media_question'] = isset($newMediaList[$question_id]) ? $newMediaList[$question_id] : 999; - } - } - - $categoriesWithQuestion[$categoryId]['question_list'][] = (int)$question_id; - } - } - return $categoriesWithQuestion; - } /** @@ -691,23 +629,35 @@ class Testcategory * Returns an array of question ids for each category * $categories[1][30] = 10, array with category id = 1 and question_id = 10 * A question has "n" categories + * @param int exercise + * @param array check question list + * @param string order by + * @return array */ - static function getQuestionsByCat($exerciseId, $check_in_question_list = array()) + static function getQuestionsByCat($exerciseId, $check_in_question_list = array(), $orderBy = null, $shuffleResult = false) { - $categories = array(); $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); + $categoryTable = Database::get_course_table(TABLE_QUIZ_CATEGORY); $exerciseId = intval($exerciseId); + if (empty($orderBy)) { + $orderBy = "c.title, category_id, question_id"; + } else { + $orderBy = Database::escape_string($orderBy); + } $sql = "SELECT DISTINCT qrc.question_id, qrc.category_id - FROM $TBL_QUESTION_REL_CATEGORY qrc, $TBL_EXERCICE_QUESTION eq + FROM $TBL_QUESTION_REL_CATEGORY qrc INNER JOIN $TBL_EXERCICE_QUESTION eq + ON (eq.question_id = qrc.question_id) + INNER JOIN $categoryTable c + ON (c.iid = qrc.category_id) WHERE exercice_id = $exerciseId 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"; + qrc.c_id = ".api_get_course_int_id()." + ORDER BY $orderBy "; $res = Database::query($sql); + + $categories = array(); while ($data = Database::fetch_array($res)) { if (!empty($check_in_question_list)) { if (!in_array($data['question_id'], $check_in_question_list)) { @@ -721,18 +671,32 @@ class Testcategory $categories[$data['category_id']][] = $data['question_id']; } + + if ($shuffleResult) { + if (!empty($categories)) { + ArrayClass::shuffle_assoc($categories); + } + } return $categories; } - /** + /** * Return an array of X elements of an array - */ - public static function getNElementsFromArray($array, $random_number) + * @param array $array + * @param int $numberOfElements + * @param bool $randomize + * @return array + */ + public static function getNElementsFromArray($array, $numberOfElements, $randomize) { - shuffle($array); - if ($random_number < count($array)) { - $array = array_slice($array, 0, $random_number); - } + if (!empty($array)) { + if ($randomize) { + shuffle($array); + } + if ($numberOfElements < count($array)) { + $array = array_slice($array, 0, $numberOfElements); + } + } return $array; } @@ -1009,7 +973,7 @@ class Testcategory * @return array */ function get_all_categories() { - $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $table = Database::get_course_table(TABLE_QUIZ_CATEGORY); $sql = "SELECT * FROM $table ORDER BY title ASC"; $res = Database::query($sql); while ($row = Database::fetch_array($res,'ASSOC')) { @@ -1022,83 +986,50 @@ class Testcategory * @param int $exercise_id * @param int $course_id * @param string $order - * @return bool + * @return array */ - public function get_category_exercise_tree($exercise_id, $course_id, $order = null) + public function getCategoryExerciseTree($exercise_id, $course_id, $order = null) { $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY); - $table_category = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY); $sql = "SELECT * FROM $table qc INNER JOIN $table_category c ON (category_id = c.iid) - WHERE exercise_id = {$exercise_id} AND qc.c_id = {$course_id} "; + WHERE exercise_id = {$exercise_id} "; if (!empty($order)) { $sql .= "ORDER BY $order"; } + $categories = array(); $result = Database::query($sql); if (Database::num_rows($result)) { + $list = array(); while ($row = Database::fetch_array($result, 'ASSOC')) { $list[$row['category_id']] = $row; } + if (!empty($list)) { - $array = $this->sort_tree_array($list); - $this->create_tree_array($array); + $categories = $this->sort_tree_array($list); } - return $this->category_array_tree; - } - return false; - } - - /** - * @param $type - * @return mixed - */ - public function get_category_tree_by_type($type) { - $course_id = api_get_course_int_id(); - if ($type == 'global') { - $course_condition = 'c_id = 0'; - } else { - $course_condition = " c_id IN ('$course_id', '0') "; - } - $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); - - $sql = "SELECT * FROM $t_cattable WHERE $course_condition"; - $res = Database::query($sql); - $categories = array(); - while ($row = Database::fetch_array($res, 'ASSOC')) { - $row['id'] = $row['iid']; - $categories[] = $row; - } - if (!empty($categories)) { - $array = $this->sort_tree_array($categories); - $this->create_tree_array($array); } - return $this->category_array_tree; + return $categories; } /** * @param $exercise_obj * @return string */ - public function return_category_form($exercise_obj) { + public function return_category_form($exercise_obj) + { $categories = $this->getListOfCategoriesForTest($exercise_obj); - if (!empty($categories)) { - $array = $this->sort_tree_array($categories); - - $this->create_tree_array($array); - } - $saved_categories = $exercise_obj->get_categories_in_exercise(); $return = null; - if (!empty($this->category_array_tree)) { + if (!empty($categories)) { $nbQuestionsTotal = $exercise_obj->getNumberQuestionExerciseCategory(); - $original_grouping = $exercise_obj->categories_grouping; $exercise_obj->setCategoriesGrouping(true); $real_question_count = count($exercise_obj->selectQuestionList(true)); - $exercise_obj->setCategoriesGrouping($original_grouping); $warning = null; if ($nbQuestionsTotal != $real_question_count) { @@ -1110,12 +1041,12 @@ class Testcategory $return .= ''; $return .= '' . get_lang('Categories') . ''; $return .= '' . get_lang('Number') . ''; - for ($i = 0; $i < count($this->category_array_tree); $i++) { - $cat_id = $this->category_array_tree[$i]['id']; + + foreach($categories as $category) { + $cat_id = $category['iid']; $return .= ''; $return .= ''; - $style = 'margin-left:' . $this->category_array_tree[$i]['depth'] * 20 . 'px; margin-right:10px;'; - $return .= Display::div($this->category_array_tree[$i]['title'], array('style' => $style)); + $return .= Display::div($category['parent_path']); $return .= ''; $return .= ''; $value = isset($saved_categories) && isset($saved_categories[$cat_id]) ? $saved_categories[$cat_id]['count_questions'] : 0; @@ -1129,10 +1060,12 @@ class Testcategory } /** + * Sorts an array * @param $array * @return mixed */ - public function sort_tree_array($array) { + public function sort_tree_array($array) + { foreach ($array as $key => $row) { $parent[$key] = $row['parent_id']; } @@ -1142,30 +1075,6 @@ class Testcategory return $array; } - /** - * @param $array - * @param int $parent - * @param $depth - * @param array $tmp - */ - public function create_tree_array($array, $parent = 0, $depth = -1, $tmp = array()) { - if (is_array($array)) { - for ($i = 0; $i < count($array); $i++) { - if ($array[$i]['parent_id'] == $parent) { - if (!in_array($array[$i]['parent_id'], $tmp)) { - $tmp[] = $array[$i]['parent_id']; - $depth++; - } - $row = $array[$i]; - $row['id'] = $array[$i]['iid']; - $row['depth'] = $depth; - $this->category_array_tree[] = $row; - $this->create_tree_array($array, $array[$i]['iid'], $depth, $tmp); - } - } - } - } - public function getForm(& $form, $action = 'new') { switch($action) { diff --git a/main/inc/ajax/model.ajax.php b/main/inc/ajax/model.ajax.php index 7ae98133a5..25b327773f 100644 --- a/main/inc/ajax/model.ajax.php +++ b/main/inc/ajax/model.ajax.php @@ -317,7 +317,7 @@ switch ($action) { case 'get_question_list': if (isset($exercise) && !empty($exercise)) { $columns = array('question', 'type', 'category', 'level', 'score', 'actions'); - $result = $exercise->getQuestionList($start, $limit, $sidx, $sord, $where_condition); + $result = $exercise->getQuestionListPagination($start, $limit, $sidx, $sord, $where_condition); } break; case 'get_group_reporting': diff --git a/main/inc/lib/display.lib.php b/main/inc/lib/display.lib.php index 2ce10e124d..e8e127ee62 100644 --- a/main/inc/lib/display.lib.php +++ b/main/inc/lib/display.lib.php @@ -1749,30 +1749,31 @@ class Display * @param string $link * @return string */ - public static function progress_pagination_bar($list, $current, $conditions = array(), $link = null, $counter = null, $addLetters = false, $fixValue = null) + public static function progress_pagination_bar($questionList, $current, $conditions = array(), $link = null, $counter = null, $addLetters = false, $fixValue = null) { if (empty($counter)) { $counter = 1; } + $fixedCounter = $counter; $pagination_size = 'pagination-mini'; $html = '