diff --git a/main/course_home/course_home.php b/main/course_home/course_home.php index f61f010ccc..ac316653a6 100644 --- a/main/course_home/course_home.php +++ b/main/course_home/course_home.php @@ -166,14 +166,73 @@ if (!isset($coursesAlreadyVisited[$course_code])) { Session::write('coursesAlreadyVisited', $coursesAlreadyVisited); } +$show_autolaunch_exercise_warning = false; + +//Exercise autolaunch +$auto_launch = api_get_course_setting('enable_exercise_auto_launch'); +if (!empty($auto_launch)) { + $session_id = api_get_session_id(); + //Exercise list + if ($auto_launch == 2) { + if (api_is_platform_admin() || api_is_allowed_to_edit()) { + $show_autolaunch_exercise_warning = true; + } else { + $session_key = 'exercise_autolunch_'.$session_id.'_'.api_get_course_int_id().'_'.api_get_user_id(); + if (!isset($_SESSION[$session_key])) { + //redirecting to the Exercise + $url = api_get_path(WEB_CODE_PATH).'exercice/exercice.php?'.api_get_cidreq().'&id_session='.$session_id; + $_SESSION[$session_key] = true; + header("Location: $url"); + exit; + } + } + } else { + $table = Database::get_course_table(TABLE_QUIZ_TEST); + $course_id = api_get_course_int_id(); + $condition = ''; + if (!empty($session_id)) { + $condition = api_get_session_condition($session_id); + $sql = "SELECT iid FROM $table WHERE c_id = $course_id AND autolaunch = 1 $condition LIMIT 1"; + $result = Database::query($sql); + //If we found nothing in the session we just called the session_id = 0 autolaunch + if (Database::num_rows($result) == 0) { + $condition = ''; + } else { + //great, there is an specific auto lunch for this session we leave the $condition + } + } + + $sql = "SELECT iid FROM $table WHERE c_id = $course_id AND autolaunch = 1 $condition LIMIT 1"; + $result = Database::query($sql); + if (Database::num_rows($result) > 0) { + $data = Database::fetch_array($result,'ASSOC'); + if (!empty($data['iid'])) { + if (api_is_platform_admin() || api_is_allowed_to_edit()) { + $show_autolaunch_exercise_warning = true; + } else { + $session_key = 'exercise_autolunch_'.$session_id.'_'.api_get_course_int_id().'_'.api_get_user_id(); + if (!isset($_SESSION[$session_key])) { + //redirecting to the LP + $url = api_get_path(WEB_CODE_PATH).'exercice/overview.php?'.api_get_cidreq().'&exerciseId='.$data['iid']; + + $_SESSION[$session_key] = true; + header("Location: $url"); + exit; + } + } + } + } + } +} /*Auto launch code */ -$show_autolunch_lp_warning = false; +$show_autolaunch_lp_warning = false; $auto_launch = api_get_course_setting('enable_lp_auto_launch'); if (!empty($auto_launch)) { $session_id = api_get_session_id(); - if ($auto_launch == 2) { //LP list + //LP list + if ($auto_launch == 2) { if (api_is_platform_admin() || api_is_allowed_to_edit()) { - $show_autolunch_lp_warning = true; + $show_autolaunch_lp_warning = true; } else { $session_key = 'lp_autolunch_'.$session_id.'_'.api_get_course_int_id().'_'.api_get_user_id(); if (!isset($_SESSION[$session_key])) { @@ -206,7 +265,7 @@ if (!empty($auto_launch)) { $lp_data = Database::fetch_array($result,'ASSOC'); if (!empty($lp_data['id'])) { if (api_is_platform_admin() || api_is_allowed_to_edit()) { - $show_autolunch_lp_warning = true; + $show_autolaunch_lp_warning = true; } else { $session_key = 'lp_autolunch_'.$session_id.'_'.api_get_course_int_id().'_'.api_get_user_id(); if (!isset($_SESSION[$session_key])) { @@ -241,9 +300,12 @@ $content = Display::return_introduction_section(TOOL_COURSE_HOMEPAGE, array( the setting homepage_view is adjustable through the platform administration section */ -if ($show_autolunch_lp_warning) { +if ($show_autolaunch_lp_warning) { $show_message .= Display::return_message(get_lang('TheLPAutoLaunchSettingIsONStudentsWillBeRedirectToAnSpecificLP'),'warning'); } +if ($show_autolaunch_exercise_warning) { + $show_message .= Display::return_message(get_lang('TheExerciseAutoLaunchSettingIsONStudentsWillBeRedirectToAnSpecificExercise'),'warning'); +} if (api_get_setting('homepage_view') == 'activity' || api_get_setting('homepage_view') == 'activity_big') { require 'activity.php'; } elseif (api_get_setting('homepage_view') == '2column') { diff --git a/main/course_info/infocours.php b/main/course_info/infocours.php index 570bfa32b1..234c1ab17f 100644 --- a/main/course_info/infocours.php +++ b/main/course_info/infocours.php @@ -325,6 +325,15 @@ $group[]=$form->createElement('radio', 'allow_fast_exercise_edition', get_lang(' $form->addGroup($group, '', array(get_lang("AllowFastExerciseEdition")), ''); +//Auto-launch Exercise LP +$form->addElement('html', '

'.Display::return_icon('quiz.png', get_lang('ConfigExercise'),'',ICON_SIZE_SMALL).' '.Security::remove_XSS(get_lang('ConfigExercise')).'

'); +$group = array(); +$group[]=$form->createElement('radio', 'enable_exercise_auto_launch', get_lang('ExerciseAutoLaunch'), get_lang('RedirectToExercise'), 1); +$group[]=$form->createElement('radio', 'enable_exercise_auto_launch', get_lang('ExerciseAutoLaunch'), get_lang('RedirectToTheExerciseList'), 2); +$group[]=$form->createElement('radio', 'enable_exercise_auto_launch', null, get_lang('Deactivate'), 0); +$form->addGroup($group, '', array(get_lang("ExerciseAutoLaunch")), ''); + + $form->addElement('style_submit_button', null, get_lang('SaveSettings'), 'class="save"'); $form->addElement('html', '
'); @@ -408,6 +417,7 @@ $values['display_info_advance_inside_homecourse'] = api_get_course_setting('di $values['email_alert_students_on_new_homework'] = api_get_course_setting('email_alert_students_on_new_homework'); $values['enable_lp_auto_launch'] = api_get_course_setting('enable_lp_auto_launch'); +$values['enable_exercise_auto_launch'] = api_get_course_setting('enable_exercise_auto_launch'); $values['pdf_export_watermark_text'] = api_get_course_setting('pdf_export_watermark_text'); $values['allow_public_certificates'] = api_get_course_setting('allow_public_certificates'); $values['allow_fast_exercise_edition'] = api_get_course_setting('allow_fast_exercise_edition') == 1 ? 1 : 0; diff --git a/main/coursecopy/classes/CourseArchiver.class.php b/main/coursecopy/classes/CourseArchiver.class.php index 0313e8789a..9c8b0ecf34 100644 --- a/main/coursecopy/classes/CourseArchiver.class.php +++ b/main/coursecopy/classes/CourseArchiver.class.php @@ -12,7 +12,8 @@ require_once 'Course.class.php'; * * @todo Use archive-folder of Chamilo? */ -class CourseArchiver { +class CourseArchiver +{ /** * Delete old temp-dirs diff --git a/main/coursecopy/classes/CourseBuilder.class.php b/main/coursecopy/classes/CourseBuilder.class.php index b351a7e42a..693b5e73f1 100644 --- a/main/coursecopy/classes/CourseBuilder.class.php +++ b/main/coursecopy/classes/CourseBuilder.class.php @@ -445,8 +445,12 @@ class CourseBuilder { $doc = Database::fetch_object($res); $obj->sound = $doc->id; } + $exercise_obj = new Exercise($course_id); + $exercise_obj->read($obj->iid); + $categories = $exercise_obj->get_categories_with_name_in_exercise(); + $obj->categories = $categories; $quiz = new Quiz($obj); - $sql = 'SELECT * FROM '.$table_rel.' WHERE c_id = '.$course_id.' AND exercice_id = '.$obj->id; + $sql = 'SELECT * FROM '.$table_rel.' WHERE c_id = '.$course_id.' AND exercice_id = '.$obj->iid; $db_result2 = Database::query($sql); while ($obj2 = Database::fetch_object($db_result2)) { $quiz->add_question($obj2->question_id, $obj2->question_order); @@ -477,14 +481,21 @@ class CourseBuilder { $sql = "SELECT * FROM $table_que WHERE c_id = $course_id "; $db_result = Database::query($sql); while ($obj = Database::fetch_object($db_result)) { - $question = new QuizQuestion($obj->id, $obj->question, $obj->description, $obj->ponderation, $obj->type, $obj->position, $obj->picture, $obj->level, $obj->extra); - $sql = 'SELECT * FROM '.$table_ans.' WHERE c_id = '.$course_id.' AND question_id = '.$obj->id; + $categories = Testcategory::getCategoryForQuestionWithCategoryData($obj->iid, $course_id, true); + $parent_info = array(); + + if (isset($obj->parent_id) && !empty($obj->parent_id)) { + $parent_info = (array) Question::read($obj->parent_id, $course_id); + } + + $question = new QuizQuestion($obj->iid, $obj->question, $obj->description, $obj->ponderation, $obj->type, $obj->position, $obj->picture, $obj->level, $obj->extra, $parent_info, $categories); + $sql = 'SELECT * FROM '.$table_ans.' WHERE c_id = '.$course_id.' AND question_id = '.$obj->iid; $db_result2 = Database::query($sql); while ($obj2 = Database::fetch_object($db_result2)) { - $question->add_answer($obj2->id, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); + $question->add_answer($obj2->iid, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); if ($obj->type == MULTIPLE_ANSWER_TRUE_FALSE) { $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $sql = 'SELECT * FROM '.$table_options.' WHERE c_id = '.$course_id.' AND question_id = '.$obj->id; + $sql = 'SELECT * FROM '.$table_options.' WHERE c_id = '.$course_id.' AND question_id = '.$obj->iid; $db_result3 = Database::query($sql); while ($obj3 = Database::fetch_object($db_result3)) { $question_option = new QuizQuestionOption($obj3); @@ -497,7 +508,7 @@ class CourseBuilder { // Building a fictional test for collecting orphan questions. $build_orphan_questions = !empty($_POST['recycle_option']); // When a course is emptied this option should be activated (true). - + //@todo fix query in order to use iid /*$sql = "SELECT questions.* FROM $table_que as questions LEFT JOIN $table_rel as quizz_questions @@ -545,8 +556,8 @@ class CourseBuilder { $db_result2 = Database::query($sql); if (Database::num_rows($db_result2)) { while ($obj2 = Database::fetch_object($db_result2)) { - $question->add_answer($obj2->id, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); - $orphanQuestionIds[] = $obj2->id; + $question->add_answer($obj2->iid, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); + $orphanQuestionIds[] = $obj2->iid; } } $this->course->add_resource($question); @@ -594,16 +605,15 @@ class CourseBuilder { exercices.active = -1)'; $db_result = Database::query($sql); if (Database::num_rows($db_result) > 0) { - $orphan_questions = new Quiz(-1, get_lang('OrphanQuestions', ''), '', 0, 0, 1, '', 0); // Tjis is the fictional test for collecting orphan questions. + // This is the fictional test for collecting orphan questions. + $orphan_questions = new Quiz(-1, get_lang('OrphanQuestions', ''), '', 0, 0, 1, '', 0); $this->course->add_resource($orphan_questions); - while ($obj = Database::fetch_object($db_result)) - { - $question = new QuizQuestion($obj->id, $obj->question, $obj->description, $obj->ponderation, $obj->type, $obj->position, $obj->picture,$obj->level,$obj->extra); - $sql = 'SELECT * FROM '.$table_ans.' WHERE question_id = '.$obj->id; + while ($obj = Database::fetch_object($db_result)) { + $question = new QuizQuestion($obj->iid, $obj->question, $obj->description, $obj->ponderation, $obj->type, $obj->position, $obj->picture,$obj->level,$obj->extra); + $sql = 'SELECT * FROM '.$table_ans.' WHERE question_id = '.$obj->iid; $db_result2 = Database::query($sql); - while ($obj2 = Database::fetch_object($db_result2)) - { - $question->add_answer($obj2->id, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); + while ($obj2 = Database::fetch_object($db_result2)) { + $question->add_answer($obj2->iid, $obj2->answer, $obj2->correct, $obj2->comment, $obj2->ponderation, $obj2->position, $obj2->hotspot_coordinates, $obj2->hotspot_type); } $this->course->add_resource($question); } diff --git a/main/coursecopy/classes/CourseRecycler.class.php b/main/coursecopy/classes/CourseRecycler.class.php index 1fc41f6c7c..6225e47cdb 100644 --- a/main/coursecopy/classes/CourseRecycler.class.php +++ b/main/coursecopy/classes/CourseRecycler.class.php @@ -314,6 +314,7 @@ class CourseRecycler $table_qui_que_rel_cat = Database :: get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); $ids = array_keys($this->course->resources[RESOURCE_QUIZ]); + $ids = array_filter($ids); // If the value "-1" is in the ids of elements (questions) to // be deleted, then consider all orphan questions should be deleted // This value is set in CourseBuilder::quiz_build_questions() @@ -323,7 +324,7 @@ class CourseRecycler if (!empty($ids)) { // Deletion of the tests first. Questions in these tests are // not deleted and become orphan at this point - $sql = "DELETE FROM ".$table_qui." WHERE c_id = ".$this->course_id." AND id IN(".$ids.")"; + $sql = "DELETE FROM ".$table_qui." WHERE c_id = ".$this->course_id." AND iid IN(".$ids.")"; Database::query($sql); $sql = "DELETE FROM ".$table_rel." WHERE c_id = ".$this->course_id." AND exercice_id IN(".$ids.")"; Database::query($sql); @@ -347,6 +348,7 @@ class CourseRecycler // active = -1 means "deleted" test. */ + //@todo fix query in order to use iid $sql = " ( SELECT q.id FROM $table_qui_que q INNER JOIN $table_rel r @@ -374,14 +376,14 @@ class CourseRecycler if (Database::num_rows($db_result) > 0) { $orphan_ids = array(); while ($obj = Database::fetch_object($db_result)) { - $orphan_ids[] = $obj->id; + $orphan_ids[] = $obj->iid; } $orphan_ids = implode(',', $orphan_ids); $sql = "DELETE FROM ".$table_rel." WHERE c_id = ".$this->course_id." AND question_id IN(".$orphan_ids.")"; Database::query($sql); $sql = "DELETE FROM ".$table_qui_ans." WHERE c_id = ".$this->course_id." AND question_id IN(".$orphan_ids.")"; Database::query($sql); - $sql = "DELETE FROM ".$table_qui_que." WHERE c_id = ".$this->course_id." AND id IN(".$orphan_ids.")"; + $sql = "DELETE FROM ".$table_qui_que." WHERE c_id = ".$this->course_id." AND iid IN(".$orphan_ids.")"; Database::query($sql); } // Also delete questions categories and options diff --git a/main/coursecopy/classes/CourseRestorer.class.php b/main/coursecopy/classes/CourseRestorer.class.php index 701826bfd5..a6d3af62a5 100644 --- a/main/coursecopy/classes/CourseRestorer.class.php +++ b/main/coursecopy/classes/CourseRestorer.class.php @@ -1508,7 +1508,7 @@ class CourseRestorer $exercise->add_exercise_to_order_table(); } - $this->course->resources[RESOURCE_QUIZ][$id]->destination_id = $new_id; + $this->course->resources[RESOURCE_QUIZ][$id]->obj->destination_id = $new_id; $order = 0; if (!empty($quiz->question_ids)) { foreach ($quiz->question_ids as $index => $question_id) { @@ -1518,6 +1518,35 @@ class CourseRestorer Database::query($sql); } } + + if ($quiz->categories) { + $exercise_obj = new Exercise($this->destination_course_id); + $exercise_obj->read($new_id); + $cats = array(); + foreach ($quiz->categories as $cat) { + $cat_from_db = new Testcategory($cat['category_id']); + if ($cat_from_db && $cat_from_db->title == $cat['title']) { + //use the same id + $cats[$cat_from_db->id] = $cat['count_questions']; + } else { + $cat_from_db = $cat_from_db->get_category_by_title($cat['title'], $this->destination_course_id); + if (empty($cat_from_db)) { + //Create a new category in this portal + if ($cat['category_id'] == 0) { + $category_c_id = 0; + } else { + $category_c_id = $this->destination_course_id; + } + $new_cat = new Testcategory(null, $cat['title'], $cat['description'], null, 'simple', $category_c_id); + $new_cat_id = $new_cat->addCategoryInBDD(); + $cats[$new_cat_id] = $cat['count_questions']; + } else { + $cats[$cat_from_db['iid']] = $cat['count_questions']; + } + } + } + $exercise_obj->save_categories_in_exercise($cats); + } } } } @@ -1543,13 +1572,26 @@ class CourseRestorer $table_options = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); // check resources inside html from fckeditor tool and copy correct urls into recipient course - $question->description = DocumentManager::replace_urls_inside_content_html_from_copy_course( - $question->description, - $this->course->code, - $this->course->destination_path, - $this->course->backup_path, - $this->course->info['path'] - ); + $question->description = DocumentManager::replace_urls_inside_content_html_from_copy_course($question->description, $this->course->code, $this->course->destination_path); + + $parent_id = 0; + + if (isset($question->parent_info)) { + $question_obj = Question::readByTitle($question->parent_info['question'], $this->destination_course_id); + + if ($question_obj) { + //Reuse media + $parent_id = $question_obj->selectId(); + } else { + //Create media + $question_obj = new MediaQuestion(); + $question_obj->updateCourse($this->destination_course_id); + $parent_id = $question_obj->save_media(array( + 'questionName' => $question->parent_info['question'], + 'questionDescription' => $question->parent_info['description'] + )); + } + } $sql = "INSERT INTO ".$table_que." SET c_id = ".$this->destination_course_id." , @@ -1560,6 +1602,7 @@ class CourseRestorer type='".self::DBUTF8escapestring($question->quiz_type)."', picture='".self::DBUTF8escapestring($question->picture)."', level='".self::DBUTF8escapestring($question->level)."', + parent_id ='".$parent_id."', extra='".self::DBUTF8escapestring($question->extra)."'"; Database::query($sql); @@ -1573,9 +1616,7 @@ class CourseRestorer // picture path $picturePath = $documentPath.'/images'; - $old_picture = api_get_path( - SYS_COURSE_PATH - ).$this->course->info['path'].'/document/images/'.$question->picture; + $old_picture = api_get_path(SYS_COURSE_PATH).$this->course->info['path'].'/document/images/'.$question->picture; if (file_exists($old_picture)) { $picture_name = 'quiz-'.$new_id.'.jpg'; @@ -1590,14 +1631,18 @@ class CourseRestorer if ($question->quiz_type == MATCHING) { $temp = array(); + $matching_list = array(); + $matching_to_update = array(); foreach ($question->answers as $index => $answer) { $temp[$answer['position']] = $answer; - } + if (!empty($answer['correct'])) { + $matching_to_update[$answer['iid']] = $answer['correct']; + } + } foreach ($temp as $index => $answer) { $sql = "INSERT INTO ".$table_ans." SET c_id = ".$this->destination_course_id." , - id = '".$index."', question_id = '".$new_id."', answer = '".self::DBUTF8escapestring($answer['answer'])."', correct = '".$answer['correct']."', @@ -1606,6 +1651,15 @@ class CourseRestorer position = '".$answer['position']."', hotspot_coordinates = '".$answer['hotspot_coordinates']."', hotspot_type = '".$answer['hotspot_type']."'"; + Database::query($sql); + $new_answer_id = Database::insert_id(); + $matching_list[$answer['iid']] = $new_answer_id; + } + //var_dump($matching_list, $matching_to_update); + foreach ($matching_to_update as $old_answer_id => $old_correct_id) { + $new_correct = $matching_list[$old_correct_id]; + $new_fixed_id = $matching_list[$old_answer_id]; + $sql = "UPDATE $table_ans SET correct = '$new_correct' WHERE iid = $new_fixed_id "; Database::query($sql); } } else { @@ -1613,24 +1667,11 @@ class CourseRestorer foreach ($question->answers as $index => $answer) { // check resources inside html from fckeditor tool and copy correct urls into recipient course - $answer['answer'] = DocumentManager::replace_urls_inside_content_html_from_copy_course( - $answer['answer'], - $this->course->code, - $this->course->destination_path, - $this->course->backup_path, - $this->course->info['path'] - ); - $answer['comment'] = DocumentManager::replace_urls_inside_content_html_from_copy_course( - $answer['comment'], - $this->course->code, - $this->course->destination_path, - $this->course->backup_path, - $this->course->info['path'] - ); + $answer['answer'] = DocumentManager::replace_urls_inside_content_html_from_copy_course($answer['answer'], $this->course->code, $this->course->destination_path); + $answer['comment'] = DocumentManager::replace_urls_inside_content_html_from_copy_course($answer['comment'], $this->course->code, $this->course->destination_path); $sql = "INSERT INTO ".$table_ans." SET c_id = ".$this->destination_course_id." , - id = '".($index + 1)."', question_id = '".$new_id."', answer = '".self::DBUTF8escapestring($answer['answer'])."', correct = '".$answer['correct']."', @@ -1640,7 +1681,8 @@ class CourseRestorer hotspot_coordinates = '".$answer['hotspot_coordinates']."', hotspot_type = '".$answer['hotspot_type']."'"; Database::query($sql); - $correct_answers[$index + 1] = $answer['correct']; + $new_answer_id = Database::insert_id(); + $correct_answers[$new_answer_id] = $answer['correct']; } } @@ -1655,41 +1697,19 @@ class CourseRestorer if ($question_option_list) { $old_option_ids = array(); foreach ($question_option_list as $item) { - $old_id = $item['id']; - unset($item['id']); + $old_id = $item['iid']; + unset($item['iid']); $item['question_id'] = $new_id; $item['c_id'] = $this->destination_course_id; $question_option_id = Database::insert($table_options, $item); $old_option_ids[$old_id] = $question_option_id; } if ($old_option_ids) { - $new_answers = Database::select( - 'id, correct', - $table_ans, - array( - 'WHERE' => array( - 'question_id = ? AND c_id = ? ' => array( - $new_id, - $this->destination_course_id - ) - ) - ) - ); + $new_answers = Database::select('iid, correct', $table_ans, array('WHERE' => array('question_id = ? AND c_id = ? '=> array($new_id, $this->destination_course_id)))); foreach ($new_answers as $answer_item) { $params = array(); $params['correct'] = $old_option_ids[$answer_item['correct']]; - $question_option_id = Database::update( - $table_ans, - $params, - array( - 'id = ? AND c_id = ? AND question_id = ? ' => array( - $answer_item['id'], - $this->destination_course_id, - $new_id - ) - ), - false - ); + $question_option_id = Database::update($table_ans, $params, array('iid = ? AND c_id = ? AND question_id = ? '=> array($answer_item['iid'], $this->destination_course_id, $new_id)), false); } } } else { @@ -1704,26 +1724,46 @@ class CourseRestorer $item['position'] = $obj->obj->position; $question_option_id = Database::insert($table_options, $item); - $new_options[$obj->obj->id] = $question_option_id; + $new_options[$obj->obj->iid] = $question_option_id; } + //var_dump($new_options, $correct_answers); foreach ($correct_answers as $answer_id => $correct_answer) { $params = array(); $params['correct'] = $new_options[$correct_answer]; - Database::update( - $table_ans, - $params, - array( - 'id = ? AND c_id = ? AND question_id = ? ' => array( - $answer_id, - $this->destination_course_id, - $new_id - ) - ), - false - ); + Database::update($table_ans, $params, array('iid = ? AND c_id = ? AND question_id = ? '=> array($answer_id, $this->destination_course_id, $new_id)), false); + } + } + } + } + + if ($question->categories) { + $cats = array(); + foreach ($question->categories as $cat) { + + $new_category = new Testcategory($cat['category_id']); + if ($new_category && $new_category->title == $cat['title']) { + $cats[] = $cat['category_id']; + } else { + $new_category = $new_category->get_category_by_title($cat['title'], $this->destination_course_id); + if (empty($new_category)) { + //Create a new category in this portal + if ($cat['category_id'] == 0) { + $category_c_id = 0; + } else { + $category_c_id = $this->destination_course_id; + } + $new_cat = new Testcategory(null, $cat['title'], $cat['description'], null, 'simple', $category_c_id); + $new_cat_id = $new_cat->addCategoryInBDD(); + $cats[] = $new_cat_id; + } else { + $cats[] = $new_category['iid']; } } } + $question = Question::read($new_id, $this->destination_course_id); + if (!empty($cats)) { + $question->saveCategories($cats); + } } $this->course->resources[RESOURCE_QUIZQUESTION][$id]->destination_id = $new_id; } diff --git a/main/coursecopy/classes/QuizQuestion.class.php b/main/coursecopy/classes/QuizQuestion.class.php index dad9fc8c41..5483ec0d45 100644 --- a/main/coursecopy/classes/QuizQuestion.class.php +++ b/main/coursecopy/classes/QuizQuestion.class.php @@ -21,43 +21,44 @@ class QuizQuestion extends Resource /** * The question */ - var $question; + public $question; /** * The description */ - var $description; + public $description; /** * Ponderation */ - var $ponderation; + public $ponderation; /** * Type */ - var $quiz_type; + public $quiz_type; /** * Position */ - var $position; + public $position; /** * Level */ - var $level; + public $level; /** * Answers */ - var $answers; + public $answers; /** * Picture */ - var $picture; - var $extra; + public $picture; + public $extra; + public $categories; /** * Create a new QuizQuestion @@ -67,7 +68,7 @@ class QuizQuestion extends Resource * @param int $type * @param int $position */ - function QuizQuestion($id, $question, $description, $ponderation, $type, $position, $picture, $level, $extra) { + function QuizQuestion($id, $question, $description, $ponderation, $type, $position, $picture, $level, $extra, $parent_info, $categories) { parent::Resource($id, RESOURCE_QUIZQUESTION); $this->question = $question; $this->description = $description; @@ -78,6 +79,8 @@ class QuizQuestion extends Resource $this->level = $level; $this->answers = array(); $this->extra = $extra; + $this->parent_info = $parent_info; + $this->categories = $categories; } /** @@ -85,7 +88,7 @@ class QuizQuestion extends Resource */ function add_answer($answer_id, $answer_text, $correct, $comment, $ponderation, $position, $hotspot_coordinates, $hotspot_type) { $answer = array(); - $answer['id'] = $answer_id; + $answer['iid'] = $answer_id; $answer['answer'] = $answer_text; $answer['correct'] = $correct; $answer['comment'] = $comment; diff --git a/main/coursecopy/classes/QuizQuestionOption.class.php b/main/coursecopy/classes/QuizQuestionOption.class.php index 11ea3b38c7..16d7db12fe 100644 --- a/main/coursecopy/classes/QuizQuestionOption.class.php +++ b/main/coursecopy/classes/QuizQuestionOption.class.php @@ -28,7 +28,7 @@ class QuizQuestionOption extends Resource * @param int $position */ function QuizQuestionOption($obj) { - parent::Resource($obj->id, RESOURCE_QUIZQUESTION); + parent::Resource($obj->iid, RESOURCE_QUIZQUESTION); $this->obj = $obj; } } \ No newline at end of file diff --git a/main/css/base.css b/main/css/base.css index 85c0fe8a91..20f4bbe60b 100644 --- a/main/css/base.css +++ b/main/css/base.css @@ -2866,6 +2866,7 @@ div.admin_section h4 { /* Fixes questions list */ .question_options { + margin-top:16px; min-height: 150px; } @@ -2938,6 +2939,7 @@ div.admin_section h4 { #question_description { padding-left: 5px; padding-top: 10px; + padding-bottom:10px; } #question_score { @@ -5147,6 +5149,43 @@ i.size-32.icon-new-work { margin-bottom: 15px; } + +.pagination .current a { + font-size: 120%; + cursor: default; +} + +.pagination .before a, .pagination .before a:hover { + background-color: #028DC2; + color:white; +} + +.pagination .after a, .pagination .after a:hover { + background-color: #F5F5F5; + color:#999999; +} + +.pagination .remind a { + text-decoration: underline; +} + +.pagination .not_answered a , .pagination .not_answered a:hover { + background-color: #f89406; +} + +.pagination .answered a , .pagination .answered a:hover { + background-color: green; +} + +.exercise_reminder_item { + font-size: 80%; +} + +.exercise_reminder_item .radio, .exercise_reminder_item .checkbox { + padding-left: 0px; +} + + .exercise_save_mini_message { margin-left: 5px; } diff --git a/main/exercice/GC.php b/main/exercice/GC.php index f3b2e99bd8..897f96ed2a 100644 --- a/main/exercice/GC.php +++ b/main/exercice/GC.php @@ -13,7 +13,7 @@ // working recursively, flag[0,1] print or delete the HotPotatoes temp files (.t.html) echo "Garbage Collector
"; -HotPotGC($_configuration['root_sys'], 1, 1); +HotPotGC(api_get_path(SYS_PATH), 1, 1); /** * Garbage collector caller function */ diff --git a/main/exercice/addlimits.php b/main/exercice/addlimits.php index d193f2a9fa..085d71a356 100644 --- a/main/exercice/addlimits.php +++ b/main/exercice/addlimits.php @@ -185,5 +185,4 @@ if (isset($_POST['ok'])) { $query = "UPDATE ".$TBL_EXERCICES." SET num_attempts = 0 WHERE id= $exercise_id"; Database::query($query); } -} -?> +} \ No newline at end of file diff --git a/main/exercice/admin.php b/main/exercice/admin.php index ad1fcc3fa5..a841777ece 100644 --- a/main/exercice/admin.php +++ b/main/exercice/admin.php @@ -248,11 +248,11 @@ if (!empty($cancelQuestion)) { } if (!empty($clone_question) && !empty($objExercise->id)) { - $old_question_obj = Question::read($clone_question); + $old_question_obj = Question::read($clone_question, api_get_course_int_id()); $old_question_obj->question = $old_question_obj->question.' - '.get_lang('Copy'); $new_id = $old_question_obj->duplicate(); - $new_question_obj = Question::read($new_id); + $new_question_obj = Question::read($new_id, api_get_course_int_id()); $new_question_obj->addToList($exerciseId); // This should be moved to the duplicate function @@ -329,10 +329,10 @@ function multiple_answer_true_false_onchange(variable) { } document.getElementById(weight_id).value = array_result[result]; } - - '; +$htmlHeadXtra[] = ''; +$htmlHeadXtra[] = ''; $htmlHeadXtra[] = " '; +$htmlHeadXtra[] = ''; + $htmlHeadXtra[] = ''; -$attempt_list = get_all_exercise_event_by_exe_id($exe_id); +$exercise_result = get_answered_questions_from_attempt($exe_id); -$remind_list = $exercise_stat_info['questions_to_check']; -$remind_list = explode(',', $remind_list); +$remind_list = $exercise_stat_info['questions_to_check']; +$remind_list = explode(',', $remind_list); -$exercise_result = array(); -foreach ($attempt_list as $question_id => $options) { - //echo $question_id.'
'; - foreach($options as $item) { +echo Display::label(get_lang('QuestionWithNoAnswer'), 'warning'); +echo '

'; - $question_obj = Question::read($item['question_id']); +$table = '
'; - switch($question_obj->type) { - case FILL_IN_BLANKS: - $item['answer'] = $objExercise->fill_in_blank_answer_to_string($item['answer']); - break; - case HOT_SPOT: +$counter = 0; +$split_by = 25; - break; - } +//$count_cols = round(count($question_list)/$split_by); +$count_cols = 3; +$span_size = 12/$count_cols; +$span_class = "span$span_size"; - if ($item['answer'] != '0' && !empty($item['answer'])) { - $exercise_result[] = $question_id; - break; - } - } -} -echo Display::label(get_lang('QuestionWithNoAnswer'), 'warning'); -echo '

'; +$table .= '
'; -$table = ''; -$counter = 0; -// Loop over all question to show results for each of them, one by one +$cols = 1; +// Loop over all question to show results for each of them, one by one foreach ($question_list as $questionId) { - // destruction of the Question object - unset($objQuestionTmp); - - // creates a temporary Question object - $objQuestionTmp = Question :: read($questionId); - // initialize question information - - $quesId = $objQuestionTmp->selectId(); - $check_id = 'remind_list['.$questionId.']'; - $attributes = array('id'=>$check_id, 'onclick'=>"save_remind_item(this, '$questionId');"); - - if (in_array($questionId, $remind_list)) { - $attributes['checked'] = 1; - } - $label_attributes = array(); - $label_attributes['class'] = 'checkbox'; - $label_attributes['for'] = $check_id; + + // creates a temporary Question object + $objQuestionTmp = Question::read($questionId); + // initialize question information + $check_id = 'remind_list['.$questionId.']'; + $attributes = array('id' => $check_id, 'onclick' => "save_remind_item(this, '$questionId');"); + + if (in_array($questionId, $remind_list)) { + $attributes['checked'] = 1; + } + $label_attributes = array(); + $label_attributes['class'] = 'checkbox'; + $label_attributes['for'] = $check_id; $label_attributes['class'] = "checkbox"; - $checkbox = Display::input('checkbox', 'remind_list['.$questionId.']', '', $attributes); - $url = 'exercise_submit.php?exerciseId='.$objExercise->id.'&num='.$counter.'&reminder=1'; + if (in_array($objQuestionTmp->type, Question::question_type_no_review())) { + $attributes['disabled'] = 'disabled'; + } + + $checkbox = Display::input('checkbox', 'remind_list['.$questionId.']', '', $attributes); + $url = 'exercise_submit.php?exerciseId='.$objExercise->id.'&num='.$counter.'&reminder=1'; - $counter++; - if ($objExercise->type == ONE_PER_PAGE) { - $question_title = Display::url($counter.'. '.Text::cut($objQuestionTmp->selectTitle(), 40), $url); - $question_title = $counter.'. '.Text::cut($objQuestionTmp->selectTitle(), 40); - } else { - $question_title = $counter.'. '.Text::cut($objQuestionTmp->selectTitle(), 40); - } + $counter++; + if ($objExercise->type == ONE_PER_PAGE) { + $question_title = Display::url($counter.'. '.Text::cut($objQuestionTmp->selectTitle(), 40), $url); + $question_title = $counter.'. '.Text::cut($objQuestionTmp->selectTitle(), 40); + } else { + $question_title = $counter.'. '.Text::cut($objQuestionTmp->selectTitle(), 40); + } //Check if the question doesn't have an answer if (!in_array($questionId, $exercise_result)) { $question_title = Display::label($question_title, 'warning'); } - $question_title = Display::tag('label', $checkbox.$question_title, $label_attributes); - $table .= Display::div($question_title, array('class'=>'exercise_reminder_item')); -} // end foreach() block that loops over all questions + $question_title = Display::tag('label', $checkbox.$question_title, $label_attributes); + $table .= Display::div($question_title, array('class' => 'exercise_reminder_item')); + + if (($counter % $split_by) == 0) { + if ($counter > 1 ) { + $table .= '
'; + if ($cols % $count_cols == 0) { + $table .= '
'; + $table .= '
'; + $table .= '
'; + } + $cols++; + } + $table .= '
'; + } +} +$table .= "
"; +$table .= "
"; -echo Display::div($table, array('class'=>'span10')); +echo Display::div($table, array('class' => 'span12')); -$exercise_actions = Display::url(get_lang('EndTest'), 'javascript://', array('onclick'=>'final_submit();', 'class'=>'btn btn-warning')); -$exercise_actions .= ' '.Display::url(get_lang('ReviewQuestions'), 'javascript://', array('onclick'=>'review_questions();','class'=>'btn btn-success')); +$exercise_actions = Display::url(get_lang('EndTest'), 'javascript://', array('onclick' => 'final_submit();', 'class' => 'btn btn-warning')); +$exercise_actions .= ' '.Display::url(get_lang('ReviewQuestions'), 'javascript://', array('onclick' => 'review_questions();', 'class' => 'btn btn-success')); -echo Display::div(' ', array('class'=>'clear')); -echo Display::div($exercise_actions, array('class'=>'form-actions')); +echo Display::div('', array('class' => 'clear')); +echo Display::div($exercise_actions, array('class' => 'form-actions')); if ($origin != 'learnpath') { - //we are not in learnpath tool - Display::display_footer(); -} + //we are not in learnpath tool + Display::display_footer(); +} \ No newline at end of file diff --git a/main/exercice/exercise_report.php b/main/exercice/exercise_report.php index bdd22d1c3e..4b32b0c866 100644 --- a/main/exercice/exercise_report.php +++ b/main/exercice/exercise_report.php @@ -497,17 +497,16 @@ $extra_params['height'] = 'auto'; '; + } echo ''; + } + + $form->addElement('select', 'questionCategory', get_lang('Category'), array(), array('id' => 'category_id')); // Categories //$tabCat = Testcategory::getCategoriesIdAndName(); //$form->addElement('select', 'questionCategory', get_lang('Category'), $tabCat); //Medias - //$course_medias = Question::prepare_course_media_select(api_get_course_int_id()); - //$form->addElement('select', 'parent_id', get_lang('AttachToMedia'), $course_medias); + $course_medias = Question::prepare_course_media_select(api_get_course_int_id()); + + $form->addElement('select', 'parent_id', get_lang('AttachToMedia'), $course_medias); $form->addElement('html', ''); } @@ -1559,12 +1625,9 @@ abstract class Question if ($objExercise->exercise_was_added_in_lp == true) { $img = pathinfo($img); $img = $img['filename'].'_na.'.$img['extension']; - echo Display::return_icon($img, $explanation); + echo Display::return_icon($img, $explanation, array(), ICON_SIZE_BIG); } else { - echo ''.Display::return_icon( - $img, - $explanation - ).''; + echo ''.Display::return_icon($img, $explanation, array(), ICON_SIZE_BIG).''; } echo ''; echo ''; @@ -1595,7 +1658,7 @@ abstract class Question $params['name'] = $name; $params['position'] = $position; $params['c_id'] = $course_id; - $result = self::readQuestionOption($question_id, $course_id); + //$result = self::readQuestionOption($question_id, $course_id); $last_id = Database::insert($TBL_EXERCICE_QUESTION_OPTION, $params); return $last_id; @@ -1622,19 +1685,17 @@ abstract class Question return $result; } - static function readQuestionOption($question_id, $course_id) - { + static function readQuestionOption($question_id, $course_id) { $TBL_EXERCICE_QUESTION_OPTION = Database::get_course_table(TABLE_QUIZ_QUESTION_OPTION); - $result = Database::select( - '*', - $TBL_EXERCICE_QUESTION_OPTION, - array( - 'where' => array('c_id = ? AND question_id = ?' => array($course_id, $question_id)), - 'order' => 'id ASC' - ) - ); - - return $result; + $result = Database::select('*', $TBL_EXERCICE_QUESTION_OPTION, array('where' => array('c_id = ? AND question_id = ?' => array($course_id, $question_id)), 'order' => 'iid ASC')); + if (!empty($result)) { + $new_result = array(); + foreach ($result as $item) { + $new_result[$item['iid']] = $item; + } + return $new_result; + } + return array(); } /** @@ -1646,7 +1707,7 @@ abstract class Question * * @return string */ - function return_header($feedback_type = null, $counter = null, $score = null) + function return_header($feedback_type = null, $counter = null, $score = null, $show_media) { $counter_label = ''; if (!empty($counter)) { @@ -1670,18 +1731,13 @@ abstract class Question } $question_title = $this->question; - // display question category, if any - //$header = Testcategory::returnCategoryAndTitle($this->id); - $show_media = null; - $header = null; + // Display question category, if any if ($show_media) { $header .= $this->show_media_content(); } $header .= Display::page_subheader2($counter_label.". ".$question_title); - $header .= Display::div( - '

'.$score_label.'

'.$score['result'].'

', - array('class' => 'ribbon') - ); + //$header .= Display::div('

'.$score_label.'

'.($score['result']).'

'.$score['result'].'
', array('class'=>'ribbon')); + $header .= Display::div('

'.$score_label.'

'.$score['result'].'

', array('class' => 'ribbon')); $header .= Display::div($this->description, array('id' => 'question_description')); return $header; @@ -1710,18 +1766,16 @@ abstract class Question // Get the max position $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" + ." ON q.iid = r.question_id" ." AND exercice_id = $quiz_id AND q.c_id = $course_id AND r.c_id = $course_id"; - $rs_max = Database::query($sql, __FILE__, __LINE__); + $rs_max = Database::query($sql); $row_max = Database::fetch_object($rs_max); $max_position = $row_max->max_position + 1; // Insert the new question $sql = "INSERT INTO $tbl_quiz_question (c_id, question, ponderation, position, type, level) - VALUES ($course_id, '".Database::escape_string( - $question_name - )."', '$max_score', $max_position, $type, $level)"; - $rs = Database::query($sql); + VALUES ($course_id, '".Database::escape_string($question_name)."', '$max_score', $max_position, $type, $level)"; + Database::query($sql); // Get the question ID $question_id = Database::get_last_insert_id(); @@ -1732,10 +1786,9 @@ abstract class Question $row_max_order = Database::fetch_object($rs_max_order); $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)" + $sql = "INSERT INTO $tbl_quiz_rel_question (c_id, question_id, exercice_id, question_order)" ." VALUES($course_id, $question_id, $quiz_id, $max_order)"; - $rs = Database::query($sql); + Database::query($sql); return $question_id; } @@ -1747,8 +1800,8 @@ abstract class Question public function get_type_icon_html() { $type = $this->selectType(); - $tabQuestionList = Question::get_question_type_list(); // [0]=file to include [1]=type name - + // [0]=file to include [1]=type name + $tabQuestionList = Question::get_question_type_list(); require_once $tabQuestionList[$type][0]; eval('$img = '.$tabQuestionList[$type][1].'::$typePicture;'); eval('$explanation = get_lang('.$tabQuestionList[$type][1].'::$explanationLangVar);'); @@ -1815,7 +1868,7 @@ abstract class Question if (!empty($medias)) { foreach ($medias as $media) { - $media_list[$media['id']] = empty($media['question']) ? get_lang('Untitled') : $media['question']; + $media_list[$media['iid']] = empty($media['question']) ? get_lang('Untitled') : $media['question']; } } @@ -1848,4 +1901,10 @@ abstract class Question return $html; } -} + + static function question_type_no_review() { + return array( + HOT_SPOT, HOT_SPOT_ORDER, HOT_SPOT_DELINEATION + ); + } +} \ No newline at end of file diff --git a/main/exercice/question_admin.inc.php b/main/exercice/question_admin.inc.php index a2ec798d7f..9f10a3dfe9 100644 --- a/main/exercice/question_admin.inc.php +++ b/main/exercice/question_admin.inc.php @@ -2,10 +2,10 @@ /* For licensing terms, see /license.txt */ /** * This script allows to manage the statements of questions. -* It is included from the script admin.php -* @package chamilo.exercise -* @author Olivier Brouckaert -* @author Julio Montoya +* It is included from the script admin.php +* @package chamilo.exercise +* @author Olivier Brouckaert +* @author Julio Montoya */ /** * Code @@ -16,10 +16,10 @@ $course_id = api_get_course_int_id(); // INIT QUESTION if (isset($_GET['editQuestion'])) { $objQuestion = Question::read ($_GET['editQuestion']); - $action = api_get_self()."?".api_get_cidreq()."&myid=1&modifyQuestion=".$modifyQuestion."&editQuestion=".$objQuestion->id; + $action = api_get_self()."?".api_get_cidreq()."&myid=1&modifyQuestion=".$modifyQuestion."&editQuestion=".$objQuestion->id."&exerciseId=$exerciseId"; } else { $objQuestion = Question :: getInstance($_REQUEST['answerType']); - $action = api_get_self()."?".api_get_cidreq()."&modifyQuestion=".$modifyQuestion."&newQuestion=".$newQuestion; + $action = api_get_self()."?".api_get_cidreq()."&modifyQuestion=".$modifyQuestion."&newQuestion=".$newQuestion."&exerciseId=$exerciseId"; } if (is_object($objQuestion)) { diff --git a/main/exercice/question_list_admin.inc.php b/main/exercice/question_list_admin.inc.php index 70ff7fb51d..8d9710a019 100644 --- a/main/exercice/question_list_admin.inc.php +++ b/main/exercice/question_list_admin.inc.php @@ -3,17 +3,12 @@ /** * Code library for HotPotatoes integration. * @package chamilo.exercise -* @author -*/ +* @author Olivier Brouckaert & Julio Montoya & Hubert Borderiou 21-10-2011 (Question by category) -/** * QUESTION LIST ADMINISTRATION * * This script allows to manage the question list * It is included from the script admin.php -* -* @author Olivier Brouckaert -* Modified by Hubert Borderiou 21-10-2011 (Question by category) */ // deletes a question from the exercise (not from the data base) @@ -156,6 +151,7 @@ if (!$inATest) { echo '
'; if ($nbrQuestions) { //Always getting list from DB + $objExercise->setCategoriesGrouping(false); $questionList = $objExercise->selectQuestionList(true); // Style for columns @@ -166,7 +162,7 @@ if (!$inATest) { $styleLevel = "width:6%; float:left; padding-top:8px; text-align:center;"; $styleScore = "width:4%; float:left; padding-top:8px; text-align:center;"; - $category_list = Testcategory::getCategoryListName(); + $category_list = Testcategory::getListOfCategoriesNameForTest($objExercise->id, false); if (is_array($questionList)) { foreach ($questionList as $id) { @@ -202,7 +198,7 @@ if (!$inATest) { $question_media = Display::label($objQuestionMedia->question, 'info'); } - $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), ICON_SIZE_MEDIUM).$question_media, array('style' => $styleType)); + $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), ICON_SIZE_MEDIUM), array('style' => $styleType)); // Question category $category_labels = Testcategory::return_category_labels($objQuestionTmp->category_list, $category_list); @@ -210,7 +206,7 @@ if (!$inATest) { if (empty($category_labels)) { $category_labels = "-"; } - $questionCategory = Display::tag('div', ''.$category_labels.'', array('style'=>$styleCat)); + $questionCategory = Display::tag('div', ''.$category_labels.$question_media.'', array('style'=>$styleCat)); // Question level $txtQuestionLevel = $objQuestionTmp->level; @@ -239,7 +235,7 @@ if (!$inATest) { echo '
'; //echo get_lang('Level').': '.$objQuestionTmp->selectLevel(); echo '
'; - showQuestion($id, false, null, null, false, true, false, true, $objExercise->feedback_type, true); + showQuestion($objQuestionTmp, false, null, null, false, true, false, true, $objExercise->feedback_type, true); echo '

'; echo '
'; echo ''; diff --git a/main/exercice/question_pool.php b/main/exercice/question_pool.php index fa3087f9d5..8c611ba996 100644 --- a/main/exercice/question_pool.php +++ b/main/exercice/question_pool.php @@ -150,10 +150,7 @@ if ($is_allowedToEdit) { $objExercise->addToList($recup); Session::write('objExercise',$objExercise); -// header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); -// exit(); - } - else if( isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) { + } else if (isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) { $list_recup = $_POST['recup']; foreach ($list_recup as $course_id => $question_data) { @@ -163,22 +160,6 @@ if ($is_allowedToEdit) { $current_course = api_get_course_info(); foreach ($question_data as $old_question_id) { - /* - $recup = intval($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 - $objQuestionTmp->addToList($fromExercise); - } - // destruction of the Question object - unset($objQuestionTmp); - if(!$objExcercise instanceOf Exercise) { - $objExercise = new Exercise(); - $objExercise->read($fromExercise); - } - // adds the question ID represented by $recup into the list of questions for the current exercise - $objExercise->addToList($recup); - */ //Reading the source question $old_question_obj = Question::read($old_question_id, $origin_course_id); @@ -211,8 +192,6 @@ if ($is_allowedToEdit) { } } Session::write('objExercise',$objExercise); -// header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise"); -// exit(); } } @@ -262,8 +241,7 @@ echo '
'; if (isset($fromExercise) && $fromExercise > 0) { echo ''.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).''; $titleAdd = get_lang('AddQuestionToTest'); - } - else { + } else { echo ''.Display::return_icon('back.png', get_lang('BackToExercisesList'),'',ICON_SIZE_MEDIUM).''; echo "".Display::return_icon('add_question.gif', get_lang('NewQu'), '', 32).""; $titleAdd = get_lang('ManageAllQuestions'); @@ -316,8 +294,7 @@ echo Display::form_row(get_lang('Course'), $select_course_html); if (empty($selected_course) || $selected_course == '-1') { $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 { +} else { $course_info = CourseManager::get_course_information_by_id($selected_course); } // If course has changed, reset the menu default @@ -365,7 +342,9 @@ echo Display::form_row(get_lang('Exercise'), $select_exercise_html); // 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); +$levels = Question::get_default_levels(); +$levels['-1'] = get_lang('All'); +$select_difficulty_html = Display::select('exerciseLevel', $levels, $exerciseLevel, array('class' => 'chzn-select', 'onchange' => 'submit_form(this);'), false); echo Display::form_row(get_lang('Difficulty'), $select_difficulty_html); @@ -413,7 +392,7 @@ if ($exerciseId > 0) { $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"; + $where .= " AND crc.c_id = $selected_course AND crc.question_id = qu.iid AND crc.category_id = $courseCategoryId"; } if (isset($exerciseLevel) && $exerciseLevel != -1) { $where .= ' AND level='.$exerciseLevel; @@ -421,22 +400,18 @@ if ($exerciseId > 0) { if (isset($answerType) && $answerType > 0) { $where .= ' AND type='.$answerType; } - $sql = "SELECT DISTINCT - id,question, - type, - level + $sql = "SELECT DISTINCT iid, question, type, level FROM $TBL_EXERCICE_QUESTION qt, $TBL_QUESTIONS qu $from WHERE - qt.question_id=qu.id + qt.question_id = qu.iid AND qt.exercice_id = $exerciseId AND qt.c_id = $selected_course AND qu.c_id = $selected_course $where - ORDER BY - question_order"; + ORDER BY question_order"; $result=Database::query($sql); while($row = Database::fetch_array($result, 'ASSOC')) { $main_question_list[] = $row; @@ -448,14 +423,14 @@ if ($exerciseId > 0) { $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"; + $level_where .= " AND crc.c_id= $selected_course AND crc.question_id = qu.iid AND crc.category_id = $courseCategoryId"; } if (isset($exerciseLevel) && $exerciseLevel!= -1 ) { $level_where = ' AND level = '.$exerciseLevel; } $answer_where = ''; if (isset($answerType) && $answerType >0 -1 ) { - $answer_where = ' AND q.type = '.$answerType; + $answer_where = ' AND type = '.$answerType; } /*$sql = "SELECT DISTINCT * FROM $TBL_QUESTIONS qu $from @@ -464,6 +439,8 @@ if ($exerciseId > 0) { WHERE c_id=$selected_course ) $level_where $answer_where";*/ + // @todo fix this query with the new iid field + $sql = " ( SELECT q.* FROM $TBL_QUESTIONS q INNER JOIN $TBL_EXERCICE_QUESTION r ON (q.c_id = r.c_id AND q.id = r.question_id) @@ -491,16 +468,14 @@ if ($exerciseId > 0) { $main_question_list[] = $row; } } else { - // // All tests for selected course - // - // if we have not selected any option in the list-box 'Filter' + // If we have not selected any option in the list-box 'Filter' $filter = ''; $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"; + $filter .= " AND crc.c_id = $selected_course AND crc.question_id = qu.iid AND crc.category_id = $courseCategoryId"; } if (isset($exerciseLevel) && $exerciseLevel != -1) { $filter .= ' AND level='.$exerciseLevel.' '; @@ -544,12 +519,13 @@ if ($exerciseId > 0) { 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'], + $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; } @@ -558,12 +534,16 @@ if ($exerciseId > 0) { } } } - } - else { - // +} 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"; + $sql = "SELECT DISTINCT qu.iid, 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.iid = qt.question_id AND + q.iid = qt.exercice_id $filter + ORDER BY session_id ASC"; $result = Database::query($sql); while($row = Database::fetch_array($result, 'ASSOC')) { $main_question_list[] = $row; @@ -599,31 +579,26 @@ if ($fromExercise <= 0) { // NOT IN A TEST - IN THE COURSE $actionIcon1 = "edit"; $actionIcon2 = "delete"; $questionTagA = 1; // we are in the course, question title can be a link to the question edit page - } - else { // NOT IN A TEST - NOT IN THE COURSE + } 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 } -} -else { // IN A TEST - IN THE COURSE +} else { // IN A TEST - IN THE COURSE if ($selected_course == api_get_course_int_id()) { $actionLabel = get_lang('Reuse'); $actionIcon1 = "add"; $actionIcon2 = ""; $questionTagA = 1; - } - else { // IN A TEST - NOT IN THE COURSE + } else { // IN A TEST - NOT IN THE COURSE $actionLabel = get_lang('Reuse'); $actionIcon1 = "clone"; $actionIcon2 = ""; $questionTagA = 0; } } -// -// display table -// +// Display table $header = array(); $header[] = array(get_lang('QuestionUpperCaseFirstLetter'), false, array("style"=>"text-align:center"), ''); $header[] = array(get_lang('Type'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), ''); @@ -635,34 +610,24 @@ $data = array(); if (is_array($main_question_list)) { $all_category_list = Testcategory::getCategoryListName($selected_course); - foreach ($main_question_list as $tabQuestion) { + foreach ($main_question_list as $question_item) { $row = array(); + $question_id_item = $question_item['iid']; //This function checks if the question can be read - $question_type = get_question_type_for_question($selected_course, $tabQuestion['id']); + $question_type = get_question_type_for_question($selected_course, $question_id_item); if (empty($question_type)) { continue; } - $row[] = get_a_tag_for_question($questionTagA, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], $tabQuestion['question']); + $row[] = get_a_tag_for_question($questionTagA, $fromExercise, $question_id_item, $question_item['type'], $question_item['question']); $row[] = $question_type; - $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, - $exerciseLevel, - $answerType, - $session_id, $exerciseId). - " ". - get_action_icon_for_question($actionIcon2, $fromExercise, $tabQuestion['id'], $tabQuestion['type'], - $tabQuestion['question'], $selected_course, $courseCategoryId, $exerciseLevel, $answerType, - $session_id, $exerciseId); + $row[] = get_question_category_for_question($selected_course, $question_id_item); + $row[] = $question_item['level']; + $row[] = get_action_icon_for_question($actionIcon1, $fromExercise, $question_id_item, $question_item['type'], $question_item['question'], $selected_course, $courseCategoryId, $exerciseLevel, $answerType, $session_id, $exerciseId). + " ". + get_action_icon_for_question($actionIcon2, $fromExercise, $question_id_item, $question_item['type'], $question_item['question'], $selected_course, $courseCategoryId, $exerciseLevel, $answerType, $session_id, $exerciseId); $data[] = $row; } } @@ -706,7 +671,6 @@ function reset_menu_exo_lvl_type() { $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) { @@ -740,23 +704,21 @@ $session_id, $exerciseId); */ -// -// return the html code for delete, add, clone, edit a question -// hubert.borderiou 13-10-2011 -// in_action = the code of the action triggered by the button -// from_exercice = the id of the current exercice from which we click on question pool -// in_questionid = the id of the current question -// in_questiontype = the code of the type of the current question -// in_questionname = the name of the question -// in_selected_course = the if of the course chosen in the FILTERING MENU -// in_courseCategoryId = the id of the category chosen in the FILTERING MENU -// in_exerciseLevel = the level of the exercice chosen in the FILTERING MENU -// in_answerType = the code of the type of the question chosen in the FILTERING MENU -// in_session_id = the id of the session_id chosen in the FILTERING MENU -// in_exercice_id = the id of the exercice chosen in the FILTERING MENU -function get_action_icon_for_question($in_action, $from_exercice, $in_questionid, $in_questiontype, $in_questionname, - $in_selected_course, $in_courseCategoryId, $in_exerciseLevel, $in_answerType, $in_session_id, $in_exercice_id -) { +/* + Return the html code for delete, add, clone, edit a question hubert.borderiou 13-10-2011 + in_action = the code of the action triggered by the button + from_exercice = the id of the current exercice from which we click on question pool + in_questionid = the id of the current question + in_questiontype = the code of the type of the current question + in_questionname = the name of the question + in_selected_course = the if of the course chosen in the FILTERING MENU + in_courseCategoryId = the id of the category chosen in the FILTERING MENU + in_exerciseLevel = the level of the exercice chosen in the FILTERING MENU + in_answerType = the code of the type of the question chosen in the FILTERING MENU + in_session_id = the id of the session_id chosen in the FILTERING MENU + in_exercice_id = the id of the exercice chosen in the FILTERING MENU + */ +function get_action_icon_for_question($in_action, $from_exercice, $in_questionid, $in_questiontype, $in_questionname, $in_selected_course, $in_courseCategoryId, $in_exerciseLevel, $in_answerType, $in_session_id, $in_exercice_id) { $res = ""; $getParams = "&selected_course=$in_selected_course&courseCategoryId=$in_courseCategoryId&exerciseId=$in_exercice_id&exerciseLevel=$in_exerciseLevel&answerType=$in_answerType&session_id=$in_session_id"; @@ -773,13 +735,13 @@ function get_action_icon_for_question($in_action, $from_exercice, $in_questionid case "add": // add if question is not already in test $myObjEx = new Exercise(); + $myObjEx->setCategoriesGrouping(false); $myObjEx->read($from_exercice); if (!$myObjEx->isInList($in_questionid)) { $res = ""; $res .= Display::return_icon("view_more_stats.gif", get_lang('InsertALinkToThisQuestionInTheExercise')); $res .= ""; - } - else { + } else { $res = "-"; } unset($myObjEx); @@ -796,8 +758,8 @@ function get_action_icon_for_question($in_action, $from_exercice, $in_questionid return $res; } -// return the icon for the question type -// hubert.borderiou 13-10-2011 +/* 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); $questionType = null; @@ -809,9 +771,8 @@ function get_question_type_for_question($in_selectedcourse, $in_questionid) { return $questionType; } -// return the name of the category for the question in a course -// hubert.borderiou 13-10-2011 -function get_question_categorie_for_question($course_id, $question_id) { +/* return the name of the category for the question in a course hubert.borderiou 13-10-2011*/ +function get_question_category_for_question($course_id, $question_id) { global $all_category_list; $objQuestionTmp = Question :: read($question_id, $course_id); return Testcategory::return_category_labels($objQuestionTmp->category_list, $all_category_list); diff --git a/main/exercice/result.php b/main/exercice/result.php index 8c339a189f..ce4b27c743 100644 --- a/main/exercice/result.php +++ b/main/exercice/result.php @@ -75,4 +75,4 @@ if ($show_headers) { display_question_list_by_attempt($objExercise, $id, false); -Display::display_footer(); +Display::display_footer(); \ No newline at end of file diff --git a/main/exercice/savescores.php b/main/exercice/savescores.php index a1a9f2b4e3..67d45cf815 100644 --- a/main/exercice/savescores.php +++ b/main/exercice/savescores.php @@ -36,6 +36,7 @@ $full_file_path = $documentPath.$test; FileManager::my_delete($full_file_path.$_user['user_id'].".t.html"); $TABLETRACK_HOTPOTATOES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES); +$tbl_learnpath_user = Database::get_course_table(TABLE_LEARNPATH_USER); $TABLE_LP_ITEM_VIEW = Database::get_course_table(TABLE_LP_ITEM_VIEW); $jscript2run = ''; diff --git a/main/exercice/testcategory.class.php b/main/exercice/testcategory.class.php index 2665d99092..68e446f189 100644 --- a/main/exercice/testcategory.class.php +++ b/main/exercice/testcategory.class.php @@ -1,73 +1,166 @@ getCategory($in_id); $this->id = $tmpobj->id; $this->name = $tmpobj->name; + $this->title = $tmpobj->name; $this->description = $tmpobj->description; + $this->parent_id = $tmpobj->parent_id; + $this->parent_path = $this->name; + + if (!empty($tmpobj->parent_id)) { + $category = new Testcategory($tmpobj->parent_id); + $this->parent_path = $category->parent_path.' > '.$this->name; } - else { + } else { $this->id = $in_id; $this->name = $in_name; $this->description = $in_description; - } + $this->parent_id = $parent_id; + } + $this->type = $type; + + if (!empty($course_id)) { + $this->course_id = $course_id; + } else { + $this->course_id = api_get_course_int_id(); + } } - /** return the Testcategory object with id=in_id + /** + * Return the Testcategory object with id=in_id + * + * @assert () === false */ 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(); + $sql = "SELECT * FROM $t_cattable WHERE iid = $in_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['title']; + $this->id = $row['iid']; + $this->title = $this->name = $row['title']; $this->description = $row['description']; + $this->parent_id = $row['parent_id']; + } else { + return false; } } - /** add Testcategory in the database if name doesn't already exists - */ + /** + * 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 title = '$v_name' AND c_id=".api_get_course_int_id(); - $result_verif = Database::query($sql_verif); - $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); - return true; - } - else { - return false; + $v_name = Database::escape_string($this->name); + $v_description = Database::escape_string($this->description); + $parent_id = intval($this->parent_id); + + $course_id = $this->course_id; + $courseCondition = " AND c_id = $course_id "; + if ($this->type == 'global') { + $course_id = ''; + $courseCondition = null; + } + // Check if name already exists + $sql = "SELECT count(*) AS nb FROM $t_cattable WHERE title = '$v_name' $courseCondition"; + $result = Database::query($sql); + $data = Database::fetch_array($result); + // lets add in BD if not the same name + if ($data['nb'] <= 0) { + $sql = "INSERT INTO $t_cattable (c_id, title, description, parent_id) VALUES ('$course_id', '$v_name', '$v_description', '$parent_id')"; + Database::query($sql); + return Database::insert_id(); + } else { + return false; } + } + + function get_category_by_title($title , $course_id = 0) { + $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $course_id = intval($course_id); + $sql = "SELECT * FROM $table WHERE title = '$title' AND c_id IN ('0', '$course_id')LIMIT 1"; + $title = Database::escape_string($title); + $result = Database::query($sql); + if (Database::num_rows($result)) { + $result = Database::store_result($result, 'ASSOC'); + return $result[0]; + } + return false; + } + /** + * + * Get categories by title for json calls + * + * @assert() === false + */ + function get_categories_by_keyword($tag) { + if (empty($tag)) { + return false; + } + $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $sql = "SELECT iid, title, c_id FROM $table WHERE 1=1 "; + $tag = Database::escape_string($tag); + + $where_condition = array(); + if (!empty($tag)) { + $condition = ' LIKE "%'.$tag.'%"'; + $where_condition = array( + "title $condition", + ); + $where_condition = ' AND ('.implode(' OR ', $where_condition).') '; + } + + switch ($this->type) { + case 'simple': + $course_condition = " AND c_id = '".api_get_course_int_id()."' "; + break; + case 'global': + $course_condition = " AND c_id = '0' "; + break; + case 'all': + $course_condition = " AND c_id IN ('0', '".api_get_course_int_id()."')"; + break; + } + + $where_condition .= $course_condition; + $order_clause = " ORDER BY title"; + $sql .= $where_condition.$order_clause; + + $result = Database::query($sql); + if (Database::num_rows($result)) { + return Database::store_result($result, 'ASSOC'); + } + return false; } /** @@ -75,12 +168,11 @@ class Testcategory { * @todo I'm removing the $in_id parameter because it seems that you're using $this->id instead of $in_id after confirmation delete this * jmontoya */ - //function removeCategory($in_id) { function removeCategory() { $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); + $sql = "DELETE FROM $t_cattable WHERE iid = $v_id"; + Database::query($sql); if (Database::affected_rows() <= 0) { return false; } else { @@ -89,20 +181,29 @@ class Testcategory { } - /** modify category name or description of category with id=in_id + /** + * Modify category name or description of category with id=in_id */ - //function modifyCategory($in_id, $in_name, $in_description) { function modifyCategory() { $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 title='$v_name', description='$v_description' WHERE id='$v_id' AND c_id=".api_get_course_int_id(); - $res = Database::query($sql); + $parent_id = intval($this->parent_id); + + //Avoid recursive categories + if ($parent_id == $v_id) { + $parent_id = 0; + } + $sql = "UPDATE $t_cattable SET + title = '$v_name', + description = '$v_description', + parent_id = '$parent_id' + WHERE iid = '$v_id'"; + Database::query($sql); if (Database::affected_rows() <= 0) { return false; - } - else { + } else { return true; } } @@ -116,7 +217,7 @@ class Testcategory { function getCategoryQuestionsNumber() { $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(); + $sql = "SELECT count(*) AS nb FROM $t_reltable WHERE category_id = $in_id"; $res = Database::query($sql); $row = Database::fetch_array($res); return $row['nb']; @@ -145,11 +246,10 @@ class Testcategory { $sql = "SELECT * FROM $t_cattable WHERE c_id=$in_courseid ORDER BY title ASC"; $res = Database::query($sql); while ($row = Database::fetch_array($res)) { - $tmpcat = new Testcategory($row['id'], $row['title'], $row['description']); + $tmpcat = new Testcategory($row['iid'], $row['title'], $row['description'], $row['parent_id']); $tabres[] = $tmpcat; } - } - else { + } 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)) { @@ -164,39 +264,68 @@ class Testcategory { 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 + * @assert () === false */ - public static function getCategoryForQuestion($in_questionid, $in_courseid = null) { + public static function getCategoryForQuestion($question_id, $in_courseid = null) { $result = array(); // 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); + $question_id = Database::escape_string($question_id); $sql = "SELECT category_id FROM $t_cattable WHERE question_id = '$question_id' AND c_id = $in_courseid"; $res = Database::query($sql); if (Database::num_rows($res) > 0) { - while ($row = Database::fetch_array($res)) { + while ($row = Database::fetch_array($res, 'ASSOC')) { $result[] = $row['category_id']; } } return $result; } - public static function getCategoryNamesForQuestion($in_questionid, $in_courseid = null, $display_into_labels = true) { + public static function getCategoryForQuestionWithCategoryData($question_id, $in_courseid = null) { $result = array(); // 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); $table_category = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); - $question_id = Database::escape_string($in_questionid); - $sql = "SELECT c.title FROM $t_cattable qc INNER JOIN $table_category c - ON (qc.category_id = c.id AND qc.c_id = $in_courseid AND c.c_id = $in_courseid) + $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 = $in_courseid"; + $res = Database::query($sql); + if (Database::num_rows($res) > 0) { + while ($row = Database::fetch_array($res, 'ASSOC')) { + $result[] = $row; + } + } + return $result; + } + + /** + * + * @param int $question_id + * @param int $course_id + * @param bool $display_into_labels + * @return string + */ + public static function getCategoryNamesForQuestion($question_id, $course_id = null, $display_into_labels = true) { + $result = array(); // result + if (empty($course_id) || $course_id == "") { + $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); + $question_id = intval($question_id); + $course_id = intval($course_id); + + $sql = "SELECT c.title, c.iid FROM $t_cattable qc INNER JOIN $table_category c + ON (qc.category_id = c.iid AND qc.c_id = $course_id) WHERE question_id = '$question_id' "; $res = Database::query($sql); if (Database::num_rows($res) > 0) { while ($row = Database::fetch_array($res)) { - $result[] = $row['title']; + $cat = new Testcategory($row['iid']); + $result[] = $cat->parent_path; } } @@ -209,9 +338,12 @@ class Testcategory { /** * true if question id has a category + * @assert () === false + * @assert (null) === false + * @assert (-1) === false */ - public static function isQuestionHasCategory($in_questionid) { - $category_list = Testcategory::getCategoryForQuestion($in_questionid); + public static function isQuestionHasCategory($question_id) { + $category_list = Testcategory::getCategoryForQuestion($question_id); if (!empty($category_list)) { return true; } @@ -225,18 +357,16 @@ class Testcategory { In this version, a question has only 1 category. Return the category id, "" if none */ - public static function getCategoryNameForQuestion($question_id, $course_id = null) { + public static function getCategoryNameForQuestion($catid, $course_id = null) { if (empty($course_id) || $course_id == "") { $course_id = api_get_course_int_id(); } $course_id = intval($course_id); - $category_list = Testcategory::getCategoryForQuestion($question_id, $course_id); - - $result = array(); // result + $result = array(); $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); $catid = Database::escape_string($catid); - $sql = "SELECT title FROM $t_cattable WHERE id='$catid' AND c_id = $course_id"; + $sql = "SELECT title FROM $t_cattable WHERE iid = '$catid' AND c_id = $course_id"; $res = Database::query($sql); $data = Database::fetch_array($res); if (Database::num_rows($res) > 0) { @@ -251,15 +381,34 @@ class Testcategory { * return : array of category id (integer) * @author hubert.borderiou 07-04-2011, Julio Montoya */ - public static function getListOfCategoriesIDForTest($exercise_id) { + public static function getListOfCategoriesIDForTest($exercise_id, $grouped_by_category = true) { // parcourir les questions d'un test, recup les categories uniques dans un tableau $categories_in_exercise = array(); - $quiz = new Exercise(); - $quiz->read($exercise_id); - $question_list = $quiz->selectQuestionList(); + $exercise = new Exercise(); + $exercise->setCategoriesGrouping($grouped_by_category); + $exercise->read($exercise_id); + $question_list = $exercise->selectQuestionList(); // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ??? - for ($i=1; $i <= count($question_list); $i++) { - $category_list = Testcategory::getCategoryForQuestion($question_list[$i]); + foreach ($question_list as $question_id) { + $category_list = Testcategory::getCategoryForQuestion($question_id); + if (!empty($category_list)) { + $categories_in_exercise = array_merge($categories_in_exercise, $category_list); + } + } + if (!empty($categories_in_exercise)) { + $categories_in_exercise = array_unique(array_filter($categories_in_exercise)); + } + return $categories_in_exercise; + } + + public static function getListOfCategoriesIDForTestObject($exercise_obj) { + // parcourir les questions d'un test, recup les categories uniques dans un tableau + $categories_in_exercise = array(); + $question_list = $exercise_obj->selectQuestionList(); + + // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ??? + foreach ($question_list as $question_id) { + $category_list = Testcategory::getCategoryForQuestion($question_id); if (!empty($category_list)) { $categories_in_exercise = array_merge($categories_in_exercise, $category_list); } @@ -277,14 +426,29 @@ class Testcategory { * hubert.borderiou 07-04-2011 * @author function rewrote by jmontoya */ - public static function getListOfCategoriesNameForTest($in_testid) { - $tabcatName = array(); - $tabcatID = self::getListOfCategoriesIDForTest($in_testid); - for ($i=0; $i < count($tabcatID); $i++) { - $cat = new Testcategory($tabcatID[$i]); - $tabcatName[$cat->id] = $cat->name; + public static function getListOfCategoriesNameForTest($exercise_id, $grouped_by_category = true) { + $result = array(); + $categories = self::getListOfCategoriesIDForTest($exercise_id, $grouped_by_category); + foreach ($categories as $cat_id) { + $cat = new Testcategory($cat_id); + if (!empty($cat->id)) { + $result[$cat->id] = $cat->name; } - return $tabcatName; + } + return $result; + } + + public static function getListOfCategoriesForTest($exercise_obj) { + $result = array(); + $categories = self::getListOfCategoriesIDForTestObject($exercise_obj); + foreach ($categories as $cat_id) { + $cat = new Testcategory($cat_id); + $cat = (array)$cat; + $cat['iid'] = $cat['id']; + $cat['title'] = $cat['name']; + $result[$cat['id']] = $cat; + } + return $result; } /** @@ -293,8 +457,8 @@ class Testcategory { * return : integer * hubert.borderiou 07-04-2011 */ - public static function getNumberOfCategoriesForTest($in_testid) { - return count(Testcategory::getListOfCategoriesIDForTest($in_testid)); + public static function getNumberOfCategoriesForTest($exercise_id) { + return count(Testcategory::getListOfCategoriesIDForTest($exercise_id)); } /** @@ -309,8 +473,8 @@ class Testcategory { $exercise->read($exercise_id); $question_list = $exercise->selectQuestionList(); // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ? ? ? - for ($i=1; $i <= count($question_list); $i++) { - $category_in_question = Testcategory::getCategoryForQuestion($question_list[$i]); + foreach ($question_list as $question_id) { + $category_in_question = Testcategory::getCategoryForQuestion($question_id); if (in_array($category_id, $category_in_question)) { $number_questions_in_category++; } @@ -329,9 +493,10 @@ class Testcategory { $list_categories = Testcategory::getListOfCategoriesIDForTest($exercise_id); if (!empty($list_categories)) { - for ($i=0; $i < count($list_categories); $i++) { - if ($list_categories[$i] > 0) { // 0 = no category for this question - $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($exercise_id, $list_categories[$i]); + foreach ($list_categories as $category_item) { + if ($category_item > 0) { + // 0 = no category for this question + $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($exercise_id, $category_item); if ($nbQuestionInThisCat > $in_nbrandom) { $nbquestionresult += $in_nbrandom; @@ -363,39 +528,48 @@ class Testcategory { } /** - * 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 + * 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 */ - static function getQuestionsByCat($in_exerciceId) { - $tabres = array(); + static function getQuestionsByCat($exerciceId, $check_in_question_list = array()) { + $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); - $in_exerciceId = intval($in_exerciceId); - $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"; + $exerciceId = intval($exerciceId); + $sql = "SELECT DISTINCT qrc.question_id, qrc.category_id + FROM $TBL_QUESTION_REL_CATEGORY qrc, $TBL_EXERCICE_QUESTION eq + WHERE exercice_id = $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; - } + if (!empty($check_in_question_list)) { + if (!in_array($data['question_id'], $check_in_question_list)) { + continue; + } + } + + if (!is_array($categories[$data['category_id']])) { + $categories[$data['category_id']] = array(); + } + $categories[$data['category_id']][] = $data['question_id']; + } + return $categories; + } /** - * return a tab of $in_number random elements of $in_tab + * Return an array of X elements of an array */ - static function getNElementsFromArray($in_tab, $in_number) { - $tabres = $in_tab; - shuffle($tabres); - if ($in_number < count($tabres)) { - $tabres = array_slice($tabres, 0, $in_number); + static function getNElementsFromArray($array, $random_number) { + shuffle($array); + if ($random_number < count($array)) { + $array = array_slice($array, 0, $random_number); } - return $tabres; + return $array; } /** @@ -412,24 +586,24 @@ class Testcategory { } /** - * sortTabByBracketLabel ($tabCategoryQuestions) - * key of $tabCategoryQuestions are the categopy id (0 for not in a category) + * key of $array are the categopy id (0 for not in a category) * value is the array of question id of this category * Sort question by Category */ - static function sortTabByBracketLabel($in_tab) { + static function sortCategoriesQuestionByName($array) { $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; + $category_array = array(); + // tab of category name + while (list($cat_id, $tabquestion) = each($array)) { + $cat = new Testcategory($cat_id); + $category_array[$cat_id] = $cat->title; } - reset($in_tab); + reset($array); // sort table by value, keeping keys as they are - asort($tabCatName); + asort($category_array); // keys of $tabCatName are keys order for $in_tab - while (list($key, $val) = each($tabCatName)) { - $tabResult[$key] = $in_tab[$key]; + while (list($key, $val) = each($category_array)) { + $tabResult[$key] = $array[$key]; } return $tabResult; } @@ -538,7 +712,7 @@ class Testcategory { if (empty($category_list)) { return null; } - $category_name_list = Testcategory::getListOfCategoriesNameForTest($exercise_id); + $category_name_list = Testcategory::getListOfCategoriesNameForTest($exercise_id, false); $table = new HTML_Table(array('class' => 'data_table')); $table->setHeaderContents(0, 0, get_lang('Categories')); @@ -581,7 +755,138 @@ class Testcategory { return null; } + function get_all_categories() { + $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); + $sql = "SELECT * FROM $table ORDER BY title ASC"; + $res = Database::query($sql); + while ($row = Database::fetch_array($res,'ASSOC')) { + $array[] = $row; + } + return $array; + } + + function get_category_exercise_tree($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); + $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} "; + + if (!empty($order)) { + $sql .= "ORDER BY $order"; + } + + $result = Database::query($sql); + if (Database::num_rows($result)) { + 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); + } + return $this->category_array_tree; + } + return false; + } + + + + 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; + } + + 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(); + + if (!empty($this->category_array_tree)) { + $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) { + $warning = Display::return_message(get_lang('CheckThatYouHaveEnoughQuestionsInYourCategories'), 'warning'); + } -} -endif; \ No newline at end of file + $return .= $warning; + $return .= ''; + $return .= ''; + $return .= ''; + $return .= ''; + for ($i = 0; $i < count($this->category_array_tree); $i++) { + $cat_id = $this->category_array_tree[$i]['id']; + $return .= ''; + $return .= ''; + $return .= ''; + $return .= ''; + } + $return .= '
' . get_lang('Categories') . '' . get_lang('Number') . '
'; + $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 .= ''; + $value = isset($saved_categories) && isset($saved_categories[$cat_id]) ? $saved_categories[$cat_id]['count_questions'] : 0; + $return .= ''; + $return .= '
'; + return $return; + } + } + + public function sort_tree_array($array) { + foreach ($array as $key => $row) { + $parent[$key] = $row['parent_id']; + } + if (count($array) > 0) { + array_multisort($parent, SORT_ASC, $array); + } + return $array; + } + + public function create_tree_array($array, $parent = 0, $depth = -1, $tmp = array()) { + if (is_array($array)) { + for ($i = 0; $i < count($array); $i++) { + //var_dump($array[$i], $parent, $tmp); + 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); + } + } + + } + } +} \ No newline at end of file diff --git a/main/exercice/tests_category.php b/main/exercice/tests_category.php index 19cf658939..7cff469fee 100644 --- a/main/exercice/tests_category.php +++ b/main/exercice/tests_category.php @@ -6,6 +6,27 @@ hubert.borderiou Manage tests category page */ +// name of the language file that needs to be included +$language_file = 'exercice'; +$nameTools = ""; + +require_once '../inc/global.inc.php'; +require_once 'exercise.lib.php'; +require_once 'question.class.php'; + +$this_section = SECTION_COURSES; + +if (!api_is_allowed_to_edit()) { + api_not_allowed(true); +} + +$type = isset($_GET['type']) ? Security::remove_XSS($_GET['type']) : 'simple'; + +if ($type == 'global' && !api_is_platform_admin()) { + api_not_allowed(true); +} + +$url = api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?type='.$type; $htmlHeadXtra[] = ' -'; -// name of the language file that needs to be included -$language_file = 'exercice'; -$nameTools = ""; + function check() { + $("#parent_id option:selected").each(function() { + var id = $(this).val(); + var name = $(this).text(); + if (id != "" ) { + $.ajax({ + async: false, + url: "'.$url.'&a=exercise_category_exists", + data: "id="+id, + success: function(return_value) { + if (return_value == 0 ) { + alert("'.get_lang('CategoryDoesNotExists').'"); + //Deleting select option tag + $("#parent_id").find("option").remove(); -require_once '../inc/global.inc.php'; -require_once 'exercise.lib.php'; -require_once 'question.class.php'; -require_once 'testcategory.class.php'; + $(".holder li").each(function () { + if ($(this).attr("rel") == id) { + $(this).remove(); + } + }); + } + }, + }); + } + }); + } -$this_section = SECTION_COURSES; + $(function() { + $("#parent_id").fcbkcomplete({ + json_url: "'.$url.'&a=search_category_parent", + maxitems: 1, + addontab: false, + input_min_size: 1, + cache: false, + complete_text:"'.get_lang('StartToType').'", + firstselected: false, + onselect: check, + filter_selected: true, + newel: true + }); + }); +'; -if (!api_is_allowed_to_edit()) { - api_not_allowed(true); -} +$htmlHeadXtra[] = ''; +$htmlHeadXtra[] = ''; -// breadcrumbs +// 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($_GET['action']); + add_category_form($_GET['action'], $type); +} else if (isset($_GET['action']) && $_GET['action'] == 'addcategoryglobal') { + add_category_form($_GET['action'], $type); } else if (isset($_GET['action']) && $_GET['action'] == 'editcategory') { - edit_category_form($_GET['action']); + edit_category_form($_GET['action'], $type); } else if (isset($_GET['action']) && $_GET['action'] == 'deletecategory') { - delete_category_form($_GET['action']); + delete_category_form($_GET['action'], $type); } else { - display_add_category(); - display_categories(); + display_add_category($type); + display_categories($type); } Display::display_footer(); // FUNCTIONS // form to edit a category -function edit_category_form($in_action) { +function edit_category_form($in_action, $type = 'simple') { $in_action = Security::remove_XSS($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); + // initiate the object + $form = new FormValidator('note', 'post', api_get_self().'?action='.$in_action.'&category_id='.$category_id."&type=".$type); - // settting the form elements + // 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('text', 'category_name', get_lang('CategoryName'), array('class' => 'span6')); $form->add_html_editor('category_description', get_lang('CategoryDescription'), false, false, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200')); + $category_parent_list = array(); + + if (!empty($objcat->parent_id)) { + $parent_cat = new Testcategory($objcat->parent_id); + $category_parent_list = array($parent_cat->id => $parent_cat->name); + echo ''; + } + + $form->addElement('select', 'parent_id', get_lang('Parent'), $category_parent_list, array('id' => 'parent_id')); $form->addElement('style_submit_button', 'SubmitNote', get_lang('ModifyCategory'), 'class="add"'); - // setting the defaults + // setting the defaults $defaults = array(); $defaults["category_id"] = $objcat->id; $defaults["category_name"] = $objcat->name; $defaults["category_description"] = $objcat->description; + $defaults["parent_id"] = $objcat->parent_id; $form->setDefaults($defaults); - // setting the rules + // setting the rules $form->addRule('category_name', get_lang('ThisFieldIsRequired'), 'required'); - // The validation or display + // The validation or display if ($form->validate()) { $check = Security::check_token('post'); if ($check) { @@ -91,7 +153,8 @@ function edit_category_form($in_action) { $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); + $parent_id = isset($values['parent_id']) ? $values['parent_id'] : null; + $objcat = new Testcategory($v_id, $v_name, $v_description, $parent_id, $type); if ($objcat->modifyCategory()) { Display::display_confirmation_message(get_lang('MofidfyCategoryDone')); } else { @@ -99,15 +162,15 @@ function edit_category_form($in_action) { } } Security::clear_token(); - display_add_category(); - display_categories(); + display_add_category($type); + display_categories($type); } else { - display_goback(); + display_goback($type); $token = Security::get_token(); $form->addElement('hidden', 'sec_token'); $form->setConstants(array('sec_token' => $token)); $form->display(); - display_categories(); + display_categories($type); } } else { Display::display_error_message(get_lang('CannotEditCategory')); @@ -115,7 +178,7 @@ function edit_category_form($in_action) { } // process to delete a category -function delete_category_form($in_action) { +function delete_category_form($in_action, $type = 'simple') { $in_action = Security::remove_XSS($in_action); if (isset($_GET['category_id']) && is_numeric($_GET['category_id'])) { $category_id = Security::remove_XSS($_GET['category_id']); @@ -132,30 +195,33 @@ function delete_category_form($in_action) { } else { Display::display_error_message(get_lang('CannotDeleteCategoryError')); } - display_add_category(); - display_categories(); + display_add_category($type); + display_categories($type); } -// form to add a category -function add_category_form($in_action) { +// Form to add a category +function add_category_form($in_action, $type = 'simple') { $in_action = Security::remove_XSS($in_action); - // initiate the object - $form = new FormValidator('note', 'post', api_get_self() . '?action=' . $in_action); - // settting the form elements + // Initiate the object + $form = new FormValidator('note', 'post', api_get_self().'?action='.$in_action."&type=".$type); + // Setting the form elements $form->addElement('header', get_lang('AddACategory')); - $form->addElement('text', 'category_name', get_lang('CategoryName'), array('size' => '95')); + $form->addElement('text', 'category_name', get_lang('CategoryName'), array('class' => 'span6')); $form->add_html_editor('category_description', get_lang('CategoryDescription'), false, false, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200')); + $form->addElement('select', 'parent_id', get_lang('Parent'), array(), array('id' => 'parent_id')); $form->addElement('style_submit_button', 'SubmitNote', get_lang('AddTestCategory'), 'class="add"'); - // setting the rules + + // 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(); + $values = $form->getSubmitValues(); $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); + $parent_id = isset($values['parent_id']) && isset($values['parent_id'][0]) ? $values['parent_id'][0] : null; + $objcat = new Testcategory(0, $v_name, $v_description, $parent_id, $type, api_get_course_int_id()); if ($objcat->addCategoryInBDD()) { Display::display_confirmation_message(get_lang('AddCategoryDone')); } else { @@ -163,59 +229,75 @@ function add_category_form($in_action) { } } Security::clear_token(); - display_add_category(); - display_categories(); + display_add_category($type); + display_categories($type); } else { - display_goback(); + display_goback($type); $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() { +function display_add_category($type) { echo '
'; echo '' . Display::return_icon('back.png', get_lang('GoBackToQuestionList'), '', ICON_SIZE_MEDIUM) . ''; - echo '' . Display::return_icon('question_category.gif', get_lang('AddACategory')) . ''; + $icon = "question_category.gif"; + if ($type == 'global') { + $icon = "folder_global_category_new.png"; + } + echo ''.Display::return_icon($icon, get_lang('AddACategory'), array(), ICON_SIZE_MEDIUM).''; echo '
'; echo "
"; + if ($type == 'simple') { echo "
" . get_lang('QuestionCategory') . "
"; + } else { + echo "
".get_lang('QuestionGlobalCategory')."
"; + } } // Display category list -function display_categories() { - $course_id = api_get_course_int_id(); - $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); - $sql = "SELECT * FROM $t_cattable WHERE c_id = $course_id ORDER BY title"; - $res = Database::query($sql); +function display_categories($type = 'simple') { + $cat = new Testcategory(); + $categories = $cat->get_category_tree_by_type($type); - while ($row = Database::fetch_array($res)) { - // le titre avec le nombre de questions qui sont dans cette cat�gorie - $tmpobj = new Testcategory($row['id']); + foreach ($categories as $row) { + // Title with number of questions in the category + $category_id = $row['id']; + $tmpobj = new Testcategory($category_id); $nb_question = $tmpobj->getCategoryQuestionsNumber(); - echo '
'; + echo '
'; $nb_question_label = $nb_question == 1 ? $nb_question . ' ' . get_lang('Question') : $nb_question . ' ' . get_lang('Questions'); + $global_label = null; + if ($row['c_id'] == 0) { + $global_label = ' '.Display::label(get_lang('Global'), 'info'); + } echo "" . $nb_question_label . ""; - echo $row['title']; + $style = 'margin-left:' . $row['depth'] * 20 . 'px; margin-right:10px;'; + echo $title = Display::div($row['title'].$global_label, array('style' => $style)); echo '
'; echo '
'; echo $row['description']; echo '
'; echo '
'; - echo '' . Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . ''; - if ($nb_question > 0) { + if ($row['c_id'] == 0 && $type == 'simple') { + echo Display::return_icon('edit_na.png', get_lang('Edit'), array(), ICON_SIZE_SMALL); + } else { + echo ''.Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL).''; + } + + if ($nb_question > 0 || ($row['c_id'] == 0 && $type == 'simple')){ echo ''; echo Display::return_icon('delete_na.png', get_lang('CannotDeleteCategory'), array(), ICON_SIZE_SMALL); echo ''; } else { $rowname = protectJSDialogQuote($row['title']); - echo ' '; + echo ' '; echo Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . ''; } echo '
'; @@ -223,9 +305,10 @@ function display_categories() { } // display goback to category list page link -function display_goback() { +function display_goback($type) { + $type = Security::remove_XSS($type); echo ''; } diff --git a/main/exercice/unique_answer.class.php b/main/exercice/unique_answer.class.php index 0668fb4569..ee6c48f2e9 100644 --- a/main/exercice/unique_answer.class.php +++ b/main/exercice/unique_answer.class.php @@ -9,9 +9,6 @@ /** * Code */ - -if(!class_exists('UniqueAnswer')): - /** CLASS UNIQUE_ANSWER * @@ -23,7 +20,8 @@ if(!class_exists('UniqueAnswer')): * @package chamilo.exercise **/ -class UniqueAnswer extends Question { +class UniqueAnswer extends Question +{ static $typePicture = 'mcua.gif'; static $explanationLangVar = 'UniqueSelect'; @@ -119,7 +117,7 @@ class UniqueAnswer extends Question { $question = Question::read($questionid); if($question) { - $select_question[$questionid]='Q'.$key.' :'.Text::cut($question->selectTitle(),20); + $select_question[$questionid] = 'Q'.$key.' :'.Text::cut($question->selectTitle(),20); } } } @@ -131,7 +129,7 @@ class UniqueAnswer extends Question { $select_lp_id[0]=get_lang('SelectTargetLP'); foreach ($flat_list as $id => $details) { - $select_lp_id[$id] = Text::cut($details['lp_name'],20); + $select_lp_id[$id] = Text::cut($details['lp_name'], 20); } $temp_scenario = array(); @@ -144,14 +142,16 @@ class UniqueAnswer extends Question { for ($i = 1 ; $i <= $nb_answers ; ++$i) { $form -> addElement ('html', ''); if (isset($answer) && is_object($answer)) { - if ($answer -> correct[$i]) { + $answer_id = $answer->getRealAnswerIdFromList($i); + + if ($answer->correct[$answer_id]) { $correct = $i; } - $defaults['answer['.$i.']'] = $answer->answer[$i]; - $defaults['comment['.$i.']'] = $answer->comment[$i]; - $defaults['weighting['.$i.']'] = Text::float_format($answer->weighting[$i], 1); + $defaults['answer['.$i.']'] = $answer->answer[$answer_id]; + $defaults['comment['.$i.']'] = $answer->comment[$answer_id]; + $defaults['weighting['.$i.']'] = float_format($answer->weighting[$answer_id], 1); - $item_list=explode('@@',$answer -> destination[$i]); + $item_list = explode('@@', $answer->destination[$answer_id]); $try = $item_list[0]; $lp = $item_list[1]; @@ -306,8 +306,7 @@ class UniqueAnswer extends Question { url= an url $destination_str=''; - foreach ($list_destination as $destination_id) - { + foreach ($list_destination as $destination_id) { $destination_str.=$destination_id.';'; }*/ @@ -379,13 +378,14 @@ class UniqueAnswer extends Question { * @assert (1,1,'','',1,1,null) === false */ function create_answer($id=1, $question_id, $answer_title, $comment = '', $score = 0, $correct = 0, $course_id = null) { - if (empty($question_id) or empty($answer_title)) { return false; } + if (empty($question_id) or empty($answer_title)) { + return false; + } $tbl_quiz_answer = Database::get_course_table(TABLE_QUIZ_ANSWER); $tbl_quiz_question = Database::get_course_table(TABLE_QUIZ_QUESTION); if (empty($course_id)) { $course_id = api_get_course_int_id(); } - $position = 1; $question_id = filter_var($question_id,FILTER_SANITIZE_NUMBER_INT); $score = filter_var($score,FILTER_SANITIZE_NUMBER_FLOAT); $correct = filter_var($correct,FILTER_SANITIZE_NUMBER_INT); @@ -396,18 +396,15 @@ class UniqueAnswer extends Question { $row_max = Database::fetch_object($rs_max); $position = $row_max->max_position + 1; // Insert a new answer - $sql = "INSERT INTO $tbl_quiz_answer " - ."(c_id, id, question_id,answer,correct,comment,ponderation,position,destination)" - ."VALUES ($course_id, $id,$question_id,'".Database::escape_string($answer_title)."'," + $sql = "INSERT INTO $tbl_quiz_answer (c_id, question_id,answer,correct,comment,ponderation,position,destination)" + ."VALUES ($course_id, $question_id,'".Database::escape_string($answer_title)."'," ."$correct,'".Database::escape_string($comment)."',$score,$position, " ." '0@@0@@0@@0')"; $rs = Database::query($sql); if ($correct) { - $sql = "UPDATE $tbl_quiz_question " - ." SET ponderation = (ponderation + $score) WHERE c_id = $course_id AND id = ".$question_id; + $sql = "UPDATE $tbl_quiz_question SET ponderation = (ponderation + $score) WHERE c_id = $course_id AND iid = ".$question_id; $rs = Database::query($sql); return $rs; } } -} -endif; +} \ No newline at end of file diff --git a/main/exercice/unique_answer_no_option.class.php b/main/exercice/unique_answer_no_option.class.php index 88b5ccb1f8..f3328ccdb2 100644 --- a/main/exercice/unique_answer_no_option.class.php +++ b/main/exercice/unique_answer_no_option.class.php @@ -10,9 +10,6 @@ /** * Code */ - -if(!class_exists('UniqueAnswerNoOption')): - /** CLASS UNIQUE_ANSWER * @@ -24,7 +21,8 @@ if(!class_exists('UniqueAnswerNoOption')): * @package chamilo.exercise **/ -class UniqueAnswerNoOption extends Question { +class UniqueAnswerNoOption extends Question +{ static $typePicture = 'mcuao.gif'; static $explanationLangVar = 'UniqueAnswerNoOption'; @@ -121,7 +119,8 @@ class UniqueAnswerNoOption extends Question { } } for ($k = 1 ; $k <= $nb_answers; ++$k) { - if ($answer->position[$k] != '666') { + $answer_id = $answer->getRealAnswerIdFromList($k); + if ($answer->position[$answer_id] != '666') { $new_list[$count] = $count; $count++; } @@ -137,25 +136,26 @@ class UniqueAnswerNoOption extends Question { foreach ($new_list as $key) { $i = $key; $form -> addElement ('html', ''); + $answer_id = $answer->getRealAnswerIdFromList($i); if (is_object($answer)) { - if($answer->position[$i] == 666) { + if ($answer->position[$answer_id] == 666) { //we set nothing } else { - if ($answer->correct[$i]) { + if ($answer->correct[$answer_id]) { $correct = $i; } - $answer_result = $answer->answer[$i]; - $weight_result = Text::float_format($answer->weighting[$i], 1); + $answer_result = $answer->answer[$answer_id]; + $weight_result = float_format($answer->weighting[$answer_id], 1); if ($nb_answers == $i) { $weight_result = '0'; } $defaults['answer['.$i.']'] = $answer_result; - $defaults['comment['.$i.']'] = $answer->comment[$i]; + $defaults['comment['.$i.']'] = $answer->comment[$answer_id]; $defaults['weighting['.$i.']'] = $weight_result; - $item_list=explode('@@',$answer -> destination[$i]); + $item_list = explode('@@', $answer->destination[$answer_id]); $try = $item_list[0]; $lp = $item_list[1]; @@ -413,5 +413,4 @@ class UniqueAnswerNoOption extends Question { $header .= ''; return $header; } -} -endif; +} \ No newline at end of file diff --git a/main/exercice/upload_exercise.php b/main/exercice/upload_exercise.php index 010ed116b4..f5a06b1987 100644 --- a/main/exercice/upload_exercise.php +++ b/main/exercice/upload_exercise.php @@ -32,14 +32,8 @@ if (!$is_allowed_to_edit) { api_not_allowed(true); } -// setting the tabs +// Setting the tabs $this_section = SECTION_COURSES; -$htmlHeadXtra[] = ""; // Action handling lp_upload_quiz_action_handling(); @@ -55,50 +49,32 @@ if ($origin != 'learnpath') { Display :: display_confirmation_message(get_lang($_GET['message'])); } } -} else { - echo ''; } // display the actions echo '
'; echo lp_upload_quiz_actions(); echo '
'; -// start the content div -echo '
'; // the main content lp_upload_quiz_main(); -// close the content div -echo '
'; - -function lp_upload_quiz_actions() -{ +function lp_upload_quiz_actions() { $lp_id = Security::remove_XSS($_GET['lp_id']); $return = ""; - $return .= ''.Display::return_icon( - 'back.png', - get_lang('BackToExercisesList'), - '', - ICON_SIZE_MEDIUM - ).''; + $return .= ''.Display::return_icon('back.png', get_lang('BackToExercisesList'), '', ICON_SIZE_MEDIUM).''; return $return; } -function lp_upload_quiz_secondary_actions() -{ +function lp_upload_quiz_secondary_actions() { $lp_id = Security::remove_XSS($_GET['lp_id']); $return .= ''; - $return .= ''.Display :: return_icon( - 'reporting32.png', - get_lang('Tracking') - ).get_lang('Tracking').''; + $return.=''.Display :: return_icon('reporting32.png', get_lang('Tracking')).get_lang('Tracking').''; return $return; } -function lp_upload_quiz_main() -{ +function lp_upload_quiz_main() { // variable initialisation $lp_id = Security::remove_XSS($_GET['lp_id']); @@ -286,13 +262,6 @@ function lp_upload_quiz_action_handling() } else { $comment = $feedback_false_list[$i][2]; } - /* - if ($id == 1) { - $comment = $feedback_true_list[$i][2]; - } elseif ($id == 2) { - $comment = $feedback_false_list[$i][2]; - } - */ // Create answer $unique_answer->create_answer($id, $question_id, $answer, $comment, $score, $correct); $id++; diff --git a/main/img/icons/32/folder_category.gif b/main/img/icons/32/folder_category.gif new file mode 100644 index 0000000000..fdf955753f Binary files /dev/null and b/main/img/icons/32/folder_category.gif differ diff --git a/main/img/icons/32/folder_global_category.png b/main/img/icons/32/folder_global_category.png new file mode 100644 index 0000000000..3f032251f1 Binary files /dev/null and b/main/img/icons/32/folder_global_category.png differ diff --git a/main/img/icons/32/folder_global_category_new.gif b/main/img/icons/32/folder_global_category_new.gif new file mode 100644 index 0000000000..8fda0d481a Binary files /dev/null and b/main/img/icons/32/folder_global_category_new.gif differ diff --git a/main/img/icons/32/folder_global_category_new.png b/main/img/icons/32/folder_global_category_new.png new file mode 100644 index 0000000000..c0f6e963ce Binary files /dev/null and b/main/img/icons/32/folder_global_category_new.png differ diff --git a/main/img/icons/64/looknfeel.png b/main/img/icons/64/looknfeel.png new file mode 100644 index 0000000000..abd6404973 Binary files /dev/null and b/main/img/icons/64/looknfeel.png differ diff --git a/main/inc/ajax/exercise.ajax.php b/main/inc/ajax/exercise.ajax.php index 44d9947296..c573bf80dd 100644 --- a/main/inc/ajax/exercise.ajax.php +++ b/main/inc/ajax/exercise.ajax.php @@ -21,6 +21,35 @@ $session_id = isset($_REQUEST['session_id']) ? intval($_REQUEST['session_id']) : $course_code = isset($_REQUEST['cidReq']) ? $_REQUEST['cidReq'] : api_get_course_id(); switch ($action) { + case 'exercise_category_exists': + $category = new Testcategory(); + $category->getCategory($_REQUEST['id']); + if (empty($category->id)) { + echo 0; + } else { + echo 1; + } + break; + case 'search_category_parent': + $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : 'simple'; + + $cat = new Testcategory(null, null, null, null, $type); + $items = $cat->get_categories_by_keyword($_REQUEST['tag']); + + $json_items = array(); + if (!empty($items)) { + foreach ($items as $item) { + if ($item['c_id'] == 0) { + $item['title'] .= " [".get_lang('Global')."]"; + } + $json_items[] = array( + 'key' => $item['iid'], + 'value' => $item['title'] + ); + } + } + echo json_encode($json_items); + break; case 'get_live_stats': if (!api_is_allowed_to_edit(null, true)) { break; @@ -212,18 +241,21 @@ switch ($action) { //Attempt id $exe_id = $_REQUEST['exe_id']; - if ($debug) error_log("exe_id = $exe_id "); - if ($debug) error_log("type = $type "); - if ($debug) error_log("choice = ".print_r($choice, 1)." "); - if ($debug) error_log("hot_spot_coordinates = ".print_r($hot_spot_coordinates,1)); - if ($debug) error_log("remind_list = ".print_r($remind_list)); + if ($debug) { + error_log("exe_id = $exe_id "); + error_log("type = $type "); + error_log("choice = ".print_r($choice, 1)." "); + error_log("hot_spot_coordinates = ".print_r($hot_spot_coordinates,1)); + error_log("remind_list = ".print_r($remind_list)); + } //Exercise information $objExercise = isset($_SESSION['objExercise']) ? $_SESSION['objExercise'] : null; //Question info $question_id = intval($_REQUEST['question_id']); - $question_list = $_SESSION['questionList']; + //$question_list = $_SESSION['questionList']; + $question_list = $_SESSION['question_list_flatten']; //If exercise or question is not set then exit if (empty($question_list) || empty($objExercise)) { @@ -297,12 +329,14 @@ switch ($action) { //Looping the question list + if ($debug) error_log("Looping question list".print_r($question_list, 1)); + if ($debug) error_log("Trying to save question: $question_id "); foreach ($question_list as $my_question_id) { - if ($debug) error_log("Saving question_id = $my_question_id "); if ($type == 'simple' && $question_id != $my_question_id) { continue; } + if ($debug) error_log("Saving question_id = $my_question_id "); $my_choice = $choice[$my_question_id]; @@ -380,17 +414,19 @@ switch ($action) { $_SESSION['duration_time'][$key] = time(); - update_event_exercise( $exe_id, - $objExercise->selectId(), - $total_score, - $total_weight, - $session_id, - $exercise_stat_info['orig_lp_id'], - $exercise_stat_info['orig_lp_item_id'], - $exercise_stat_info['orig_lp_item_view_id'], - $duration, - 'incomplete', - $remind_list); + update_event_exercise( + $exe_id, + $objExercise->selectId(), + $total_score, + $total_weight, + $session_id, + $exercise_stat_info['orig_lp_id'], + $exercise_stat_info['orig_lp_item_id'], + $exercise_stat_info['orig_lp_item_view_id'], + $duration, + 'incomplete', + $remind_list + ); // Destruction of the Question object unset($objQuestionTmp); diff --git a/main/inc/ajax/model.ajax.php b/main/inc/ajax/model.ajax.php index d24de69e03..477919ba22 100644 --- a/main/inc/ajax/model.ajax.php +++ b/main/inc/ajax/model.ajax.php @@ -38,12 +38,20 @@ if (!in_array($action, array( 'get_timelines', 'get_user_skill_ranking', 'get_usergroups_teacher', - 'get_question_list' + 'get_question_list', + 'get_user_list_plugin_widescale' )) ) { api_protect_admin_script(true); } +if ($action == 'get_user_list_plugin_widescale') { + $allowed = api_is_drh() || api_is_platform_admin(); + if (!$allowed) { + api_not_allowed(); + } +} + //Search features $ops = array( @@ -181,6 +189,9 @@ if (!$sidx) $sidx = 1; //@todo rework this switch ($action) { + case 'get_user_list_plugin_widescale': + $count = UserManager::get_user_data(null, null, null, null, true); + break; case 'get_question_list': require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.class.php'; $exerciseId = isset($_REQUEST['exerciseId']) ? $_REQUEST['exerciseId'] : null; @@ -320,6 +331,11 @@ $is_allowedToEdit = api_is_allowed_to_edit(null,true) || api_is_allowed_to_edit( $columns = array(); switch ($action) { + case 'get_user_list_plugin_widescale': + $columns = array('username', 'firstname', 'lastname', 'exam_password'); + $column_names = array(get_lang('Username'), get_lang('Firstname'), get_lang('Lastname'), get_lang('Password')); + $result = UserManager::get_user_data($start, $limit, $sidx, $sord); + break; case 'get_question_list': if (isset($exercise) && !empty($exercise)) { $columns = array('question', 'type', 'category', 'level', 'score', 'actions'); @@ -333,6 +349,11 @@ switch ($action) { case 'get_course_exercise_medias': $columns = array('question'); $result = Question::get_course_medias($course_id, $start, $limit, $sidx, $sord, $where_condition); + if (!empty($result)) { + foreach ($result as &$media) { + $media['id'] = $media['iid']; + } + } break; case 'get_user_course_report_resumed': $columns = array('extra_ruc', 'training_hours', 'count_users', 'count_users_registered', 'average_hours_per_user', 'count_certificates'); @@ -553,7 +574,7 @@ switch ($action) { $group['sessions'] = count($obj->get_sessions_by_usergroup($group['id'])); $group['courses'] = count($obj->get_courses_by_usergroup($group['id'])); $group['users'] = count($obj->get_users_by_usergroup($group['id'])); - switch($group['group_type']) { + switch ($group['group_type']) { case '0': $group['group_type'] = Display::label(get_lang('Class'), 'info'); break; @@ -668,7 +689,8 @@ $allowed_actions = array( 'get_user_course_report', 'get_user_course_report_resumed', 'get_group_reporting', - 'get_question_list' + 'get_question_list', + 'get_user_list_plugin_widescale' ); //5. Creating an obj to return a json diff --git a/main/inc/global.inc.php b/main/inc/global.inc.php index 7a26ed756a..e652d2f7c4 100644 --- a/main/inc/global.inc.php +++ b/main/inc/global.inc.php @@ -100,6 +100,12 @@ require_once $includePath.'/lib/internationalization_internal.lib.php'; // Do not over-use this variable. It is only for this script's local use. $libPath = $includePath.'/lib/'; +// Database constants +require_once $libPath.'database.constants.inc.php'; + +// @todo Rewrite the events.lib.inc.php in a class +require_once $libPath.'events.lib.inc.php'; + /** Loading config files */ if ($alreadyInstalled) { $configPath = $includePath.'/../../config/'; @@ -333,6 +339,115 @@ $app['form.extensions'] = $app->share($app->extend('form.extensions', function ( return $extensions; }));*/ + +// Setting Doctrine service provider (DBAL) +if (isset($app['configuration']['main_database'])) { + + $app->register(new Silex\Provider\DoctrineServiceProvider(), array( + 'db.options' => array( + 'driver' => 'pdo_mysql', + 'dbname' => $app['configuration']['main_database'], + 'user' => $app['configuration']['db_user'], + 'password' => $app['configuration']['db_password'], + 'host' => $app['configuration']['db_host'], + 'charset' => 'utf8', + /*'driverOptions' => array( + 1002 => 'SET NAMES utf8' + )*/ + ) + )); + + // Setting Doctrine ORM + $app->register(new Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider, array( + 'orm.auto_generate_proxies' => true, + "orm.proxies_dir" => $app['db.orm.proxies_dir'], + //'orm.proxies_namespace' => '\Doctrine\ORM\Proxy\Proxy', + "orm.em.options" => array( + "mappings" => array( + array( + //If true, only simple notations like @Entity will work. If false, more advanced notations and aliasing via use will work. (Example: use Doctrine\ORM\Mapping AS ORM, @ORM\Entity) + 'use_simple_annotation_reader' => false, + "type" => "annotation", + "namespace" => "Entity", + "path" => api_get_path(INCLUDE_PATH).'Entity', + ) + ), + ), + )); + + // Temporal fix to load gedmo libs + $sortableGroup = new Gedmo\Mapping\Annotation\SortableGroup(array()); + $sortablePosition = new Gedmo\Mapping\Annotation\SortablePosition(array()); + + // Setting Doctrine2 extensions + $timestampableListener = new \Gedmo\Timestampable\TimestampableListener(); + $app['db.event_manager']->addEventSubscriber($timestampableListener); + + $sluggableListener = new \Gedmo\Sluggable\SluggableListener(); + $app['db.event_manager']->addEventSubscriber($sluggableListener); + + $sortableListener = new Gedmo\Sortable\SortableListener(); + $app['db.event_manager']->addEventSubscriber($sortableListener); +} + +// Connect to the server database and select the main chamilo database. +if (!($conn_return = @Database::connect( + array( + 'server' => $app['configuration']['db_host'], + 'username' => $app['configuration']['db_user'], + 'password' => $app['configuration']['db_password'], + 'persistent' => isset($app['configuration']['db_persistent_connection']) ? $app['configuration']['db_persistent_connection'] : null + // When $app['configuration']['db_persistent_connection'] is set, it is expected to be a boolean type. + ) +)) +) { + //$app->abort(500, "Database is unavailable"); //error 3 +} + +/* +if (!$app['configuration']['db_host']) { + //$app->abort(500, "Database is unavailable"); //error 3 +}*/ + +$charset = 'UTF-8'; +$checkConnection = false; + +if (isset($app['configuration']['main_database'])) { + // The system has not been designed to use special SQL modes that were introduced since MySQL 5. + Database::query("set session sql_mode='';"); + + $checkConnection = @Database::select_db($app['configuration']['main_database'], $conn_return); + + if ($checkConnection) { + + // Initialization of the database encoding to be used. + Database::query("SET SESSION character_set_server='utf8';"); + Database::query("SET SESSION collation_server='utf8_general_ci';"); + + /* Initialization of the default encodings */ + + // The platform's character set must be retrieved at this early moment. + /*$sql = "SELECT selected_value FROM settings_current WHERE variable = 'platform_charset';"; + + $result = Database::query($sql); + while ($row = @Database::fetch_array($result)) { + $charset = $row[0]; + } + if (empty($charset)) { + $charset = 'UTF-8'; + }*/ + //Charset is UTF-8 + + if (api_is_utf8($charset)) { + // See Bug #1802: For UTF-8 systems we prefer to use "SET NAMES 'utf8'" statement in order to avoid a bizarre problem with Chinese language. + Database::query("SET NAMES 'utf8';"); + } else { + Database::query("SET CHARACTER SET '".Database::to_db_encoding($charset)."';"); + } + Database::query("SET NAMES 'utf8';"); + } +} + // The script is allowed? This setting is modified when calling api_is_not_allowed() $app['allowed'] = true; @@ -430,54 +545,6 @@ if (is_writable($app['temp.path'])) { ); } -// Setting Doctrine service provider (DBAL) -if (isset($app['configuration']['main_database'])) { - - $app->register(new Silex\Provider\DoctrineServiceProvider(), array( - 'db.options' => array( - 'driver' => 'pdo_mysql', - 'dbname' => $app['configuration']['main_database'], - 'user' => $app['configuration']['db_user'], - 'password' => $app['configuration']['db_password'], - 'host' => $app['configuration']['db_host'], - 'driverOptions' => array( - 1002 => 'SET NAMES utf8' - ) - ) - )); - - // Setting Doctrine ORM - $app->register(new Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider, array( - 'orm.auto_generate_proxies' => true, - "orm.proxies_dir" => $app['db.orm.proxies_dir'], - //'orm.proxies_namespace' => '\Doctrine\ORM\Proxy\Proxy', - "orm.em.options" => array( - "mappings" => array( - array( - //If true, only simple notations like @Entity will work. If false, more advanced notations and aliasing via use will work. (Example: use Doctrine\ORM\Mapping AS ORM, @ORM\Entity) - 'use_simple_annotation_reader' => false, - "type" => "annotation", - "namespace" => "Entity", - "path" => api_get_path(INCLUDE_PATH).'Entity', - ) - ), - ), - )); - - // Temporal fix to load gedmo libs - $sortableGroup = new Gedmo\Mapping\Annotation\SortableGroup(array()); - $sortablePosition = new Gedmo\Mapping\Annotation\SortablePosition(array()); - - // Setting Doctrine2 extensions - $timestampableListener = new \Gedmo\Timestampable\TimestampableListener(); - $app['db.event_manager']->addEventSubscriber($timestampableListener); - - $sluggableListener = new \Gedmo\Sluggable\SluggableListener(); - $app['db.event_manager']->addEventSubscriber($sluggableListener); - - $sortableListener = new Gedmo\Sortable\SortableListener(); - $app['db.event_manager']->addEventSubscriber($sortableListener); -} define('IMAGE_PROCESSOR', 'gd'); // imagick or gd strings @@ -534,68 +601,6 @@ if ($app['debug'] && isset($app['configuration']['main_database'])) { }); } -// Database constants -require_once $libPath.'database.constants.inc.php'; -// @todo Rewrite the events.lib.inc.php in a class -require_once $libPath.'events.lib.inc.php'; - -// Connect to the server database and select the main chamilo database. -if (!($conn_return = @Database::connect( - array( - 'server' => $app['configuration']['db_host'], - 'username' => $app['configuration']['db_user'], - 'password' => $app['configuration']['db_password'], - 'persistent' => isset($app['configuration']['db_persistent_connection']) ? $app['configuration']['db_persistent_connection'] : null - // When $app['configuration']['db_persistent_connection'] is set, it is expected to be a boolean type. - ) -)) -) { - //$app->abort(500, "Database is unavailable"); //error 3 -} - -/* -if (!$app['configuration']['db_host']) { - //$app->abort(500, "Database is unavailable"); //error 3 -}*/ - -$charset = 'UTF-8'; -$checkConnection = false; - -if (isset($app['configuration']['main_database'])) { - // The system has not been designed to use special SQL modes that were introduced since MySQL 5. - Database::query("set session sql_mode='';"); - - $checkConnection = @Database::select_db($app['configuration']['main_database'], $conn_return); - - if ($checkConnection) { - - // Initialization of the database encoding to be used. - Database::query("SET SESSION character_set_server='utf8';"); - Database::query("SET SESSION collation_server='utf8_general_ci';"); - - /* Initialization of the default encodings */ - - // The platform's character set must be retrieved at this early moment. - /*$sql = "SELECT selected_value FROM settings_current WHERE variable = 'platform_charset';"; - - $result = Database::query($sql); - while ($row = @Database::fetch_array($result)) { - $charset = $row[0]; - } - if (empty($charset)) { - $charset = 'UTF-8'; - }*/ - //Charset is UTF-8 - - if (api_is_utf8($charset)) { - // See Bug #1802: For UTF-8 systems we prefer to use "SET NAMES 'utf8'" statement in order to avoid a bizarre problem with Chinese language. - Database::query("SET NAMES 'utf8';"); - } else { - Database::query("SET CHARACTER SET '".Database::to_db_encoding($charset)."';"); - } - Database::query("SET NAMES 'utf8';"); - } -} // Preserving the value of the global variable $charset. $charset_initial_value = $charset; diff --git a/main/inc/lib/database.constants.inc.php b/main/inc/lib/database.constants.inc.php index bedd60368d..32f52e7be0 100644 --- a/main/inc/lib/database.constants.inc.php +++ b/main/inc/lib/database.constants.inc.php @@ -198,8 +198,9 @@ define('TABLE_QUIZ_ORDER', 'quiz_order'); 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_CATEGORY', 'quiz_category'); define('TABLE_QUIZ_QUESTION_REL_CATEGORY', 'quiz_question_rel_category'); +define('TABLE_QUIZ_REL_CATEGORY', 'quiz_rel_category'); // Linked resource table //@todo table exists? @@ -303,13 +304,13 @@ define('TABLE_THEMATIC_ADVANCE','thematic_advance'); //User groups //Needed for migration define('TABLE_MAIN_GROUP', 'groups'); + /* define('TABLE_MAIN_USER_REL_GROUP', 'group_rel_user'); define('TABLE_MAIN_GROUP_REL_TAG', 'group_rel_tag'); define('TABLE_MAIN_GROUP_REL_GROUP', 'group_rel_group'); */ - // Careers, promotions, Usergroups define('TABLE_CAREER', 'career'); define('TABLE_PROMOTION', 'promotion'); @@ -353,4 +354,3 @@ define('TABLE_BRANCH_SYNC_LOG', 'branch_sync_log'); define('TABLE_BRANCH_TRANSACTION', 'branch_transaction'); define('TABLE_BRANCH_TRANSACTION_STATUS', 'branch_transaction_status'); - diff --git a/main/inc/lib/database.lib.php b/main/inc/lib/database.lib.php index 033e391f5b..df7cdf6432 100644 --- a/main/inc/lib/database.lib.php +++ b/main/inc/lib/database.lib.php @@ -723,6 +723,8 @@ class Database */ public static function query($query, $connection = null, $file = null, $line = null) { + //bad idea ... + //global $app;return $app['db']->executeQuery($query); $use_default_connection = self::use_default_connection($connection); if ($use_default_connection) { // Let us do parameter shifting, thus the method would be similar @@ -771,6 +773,9 @@ class Database strpos($query, 'ALTER') === false && strpos($query, 'alter') === false && strpos($query, 'c_id') === false && + strpos($query, 'c_quiz_question_rel_category') === false && + strpos($query, 'c_quiz_category') === false && + strpos($query, 'create table') === false && strpos($query, 'CREATE TABLE') === false && strpos($query, 'AUTO_INCREMENT') === false diff --git a/main/inc/lib/display.lib.php b/main/inc/lib/display.lib.php index 3c0b0fed03..e37b3f8822 100644 --- a/main/inc/lib/display.lib.php +++ b/main/inc/lib/display.lib.php @@ -1718,4 +1718,62 @@ class Display
'; return $html; } -} //end class Display + + static function progress_pagination_bar($list, $current, $conditions = array(), $link = null) { + $counter = 1; + $pagination_size = ''; + $total = count($list); + if ($total > 25) { + $pagination_size = 'pagination-small'; + } + if ($total > 50) { + $pagination_size = 'pagination-mini'; + } + $html = ''; + return $html; + } +} \ No newline at end of file diff --git a/main/inc/lib/events.lib.inc.php b/main/inc/lib/events.lib.inc.php index 382830d342..811b9688c8 100644 --- a/main/inc/lib/events.lib.inc.php +++ b/main/inc/lib/events.lib.inc.php @@ -328,8 +328,7 @@ function event_link($link_id) * @author Julio Montoya Armas Reworked 2010 * @desc Record result of user when an exercice was done */ -function update_event_exercise($exeid, $exo_id, $score, $weight, $session_id, $learnpath_id = 0, $learnpath_item_id = 0, $learnpath_item_view_id = 0, $duration = 0, $status = '', $remind_list = array(), $end_date = null) -{ +function update_event_exercise($exeid, $exo_id, $score, $weigh, $session_id, $learnpath_id = 0, $learnpath_item_id = 0, $learnpath_item_view_id = 0, $duration = 0, $status = '', $remind_list = array() , $end_date = null) { require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.lib.php'; global $debug; if ($debug) { @@ -1571,6 +1570,32 @@ function delete_attempt_hotspot($exe_id, $user_id, $courseId, $question_id) Database::query($sql); } +function get_answered_questions_from_attempt($exe_id, $objExercise) { + $attempt_list = get_all_exercise_event_by_exe_id($exe_id); + $exercise_result = array(); + if (!empty($attempt_list)) { + foreach ($attempt_list as $question_id => $options) { + foreach ($options as $item) { + $question_obj = Question::read($item['question_id']); + switch ($question_obj->type) { + case FILL_IN_BLANKS: + $item['answer'] = $objExercise->fill_in_blank_answer_to_string($item['answer']); + break; + case HOT_SPOT: + //var_dump($item['answer']); + break; + } + + if ($item['answer'] != '0' && !empty($item['answer'])) { + $exercise_result[] = $question_id; + break; + } + } + } + } + return $exercise_result; +} + /** * User logs in for the first time to a course * @param $course_code @@ -1626,7 +1651,8 @@ function check_if_mail_already_sent($event_name, $user_from, $user_to = null) $result = Database::store_result(Database::query($sql), 'ASSOC'); return $result[0]["total"]; } -/* + +/** * * Filter EventEmailTemplate Filters see the main/inc/conf/events.conf.dist.php * diff --git a/main/inc/lib/plugin.lib.php b/main/inc/lib/plugin.lib.php index 35f8b3a47d..f90c20dde9 100644 --- a/main/inc/lib/plugin.lib.php +++ b/main/inc/lib/plugin.lib.php @@ -1,28 +1,23 @@ get_plugin_info($plugin_name); if (isset($plugin_info['plugin_class'])) { @@ -428,7 +425,8 @@ class AppPlugin { } } } - unset($obj); unset($plugin_info); + unset($obj); + unset($plugin_info); } return $settings; } diff --git a/main/inc/local.inc.php b/main/inc/local.inc.php index 45f28aff07..1ec09b5188 100644 --- a/main/inc/local.inc.php +++ b/main/inc/local.inc.php @@ -478,6 +478,7 @@ $_user = Session::read('_user'); $app['current_user'] = $_user; /* USER INIT */ + if (isset($uidReset) && $uidReset) { // session data refresh requested unset($_SESSION['_user']['uidReset']); $is_platformAdmin = false; @@ -506,7 +507,6 @@ if (isset($uidReset) && $uidReset) { // session data refresh requested $uData = Database::fetch_array($result); $_user = _api_format_user($uData, false); $_user['lastLogin'] = api_strtotime($uData['login_date'], 'UTC'); - $is_platformAdmin = (bool) (! is_null( $uData['is_admin'])); $is_allowedCreateCourse = (bool) (($uData ['status'] == COURSEMANAGER) or (api_get_setting('drhCourseManagerRights') and $uData['status'] == DRH)); ConditionalLogin::check_conditions($uData); diff --git a/main/install/1.10.0/db_course.sql b/main/install/1.10.0/db_course.sql index 9ba5f65666..3773a291ff 100644 --- a/main/install/1.10.0/db_course.sql +++ b/main/install/1.10.0/db_course.sql @@ -1280,8 +1280,8 @@ DROP TABLE IF EXISTS c_quiz; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz ( - c_id int(11) NOT NULL, - id int(10) unsigned NOT NULL AUTO_INCREMENT, + iid int unsigned NOT NULL auto_increment, + c_id int(11) NOT NULL, title varchar(255) NOT NULL, description text, sound varchar(255) DEFAULT NULL, @@ -1303,8 +1303,8 @@ CREATE TABLE c_quiz ( text_when_finished text, display_category_name int(11) NOT NULL DEFAULT '1', pass_percentage int(11) DEFAULT NULL, - PRIMARY KEY (c_id,id), - KEY session_id (session_id) + autolaunch INT DEFAULT 0, + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1316,9 +1316,8 @@ DROP TABLE IF EXISTS c_quiz_answer; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz_answer ( - c_id int(11) NOT NULL, - id int(10) unsigned NOT NULL, - id_auto int(11) NOT NULL AUTO_INCREMENT, + iid bigint unsigned NOT NULL AUTO_INCREMENT, + c_id int(11) NOT NULL, question_id int(10) unsigned NOT NULL, answer text NOT NULL, correct mediumint(8) unsigned DEFAULT NULL, @@ -1329,8 +1328,7 @@ CREATE TABLE c_quiz_answer ( hotspot_type enum('square','circle','poly','delineation','oar') DEFAULT NULL, destination text NOT NULL, answer_code char(10) DEFAULT '', - PRIMARY KEY (c_id,id_auto), - KEY idx_quiz_answer_c_q (c_id,question_id) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1342,12 +1340,12 @@ DROP TABLE IF EXISTS c_quiz_order; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz_order ( - id int(10) unsigned NOT NULL AUTO_INCREMENT, + iid bigint unsigned NOT NULL auto_increment, c_id int(10) unsigned NOT NULL, session_id int(10) unsigned NOT NULL, exercise_id int(11) NOT NULL, exercise_order int(11) NOT NULL, - PRIMARY KEY (id) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1359,8 +1357,8 @@ DROP TABLE IF EXISTS c_quiz_question; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz_question ( - c_id int(11) NOT NULL, - id int(10) unsigned NOT NULL AUTO_INCREMENT, + iid bigint unsigned NOT NULL auto_increment, + c_id int(11) NOT NULL, question text NOT NULL, description text, ponderation float(6,2) NOT NULL DEFAULT '0.00', @@ -1371,24 +1369,24 @@ CREATE TABLE c_quiz_question ( extra varchar(255) DEFAULT NULL, question_code char(10) DEFAULT '', parent_id int(10) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (c_id,id), - KEY position (position) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table c_quiz_question_category +-- Table structure for table c_quiz_category -- -DROP TABLE IF EXISTS c_quiz_question_category; +DROP TABLE IF EXISTS c_quiz_category; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE c_quiz_question_category ( - c_id int(11) NOT NULL, - id int(11) NOT NULL AUTO_INCREMENT, +CREATE TABLE c_quiz_category ( + iid bigint unsigned NOT NULL AUTO_INCREMENT, + parent_id int unsigned NOT NULL default 0, + c_id int(11) NOT NULL, title varchar(255) NOT NULL, description text NOT NULL, - PRIMARY KEY (c_id,id) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1400,12 +1398,12 @@ DROP TABLE IF EXISTS c_quiz_question_option; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz_question_option ( + iid bigint unsigned NOT NULL auto_increment, c_id int(11) NOT NULL, - id int(11) NOT NULL AUTO_INCREMENT, question_id int(11) NOT NULL, name varchar(255) DEFAULT NULL, position int(10) unsigned NOT NULL, - PRIMARY KEY (c_id,id) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1417,10 +1415,11 @@ DROP TABLE IF EXISTS c_quiz_question_rel_category; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz_question_rel_category ( + iid bigint unsigned NOT NULL AUTO_INCREMENT, c_id int(11) NOT NULL, question_id int(11) NOT NULL, category_id int(11) NOT NULL, - PRIMARY KEY (c_id,question_id) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; @@ -1432,11 +1431,12 @@ DROP TABLE IF EXISTS c_quiz_rel_question; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE c_quiz_rel_question ( + iid bigint unsigned NOT NULL AUTO_INCREMENT, c_id int(11) NOT NULL, question_id int(10) unsigned NOT NULL, exercice_id int(10) unsigned NOT NULL, question_order int(10) unsigned NOT NULL DEFAULT '1', - PRIMARY KEY (c_id,question_id,exercice_id) + PRIMARY KEY (iid) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/main/install/1.10.0/db_main.sql b/main/install/1.10.0/db_main.sql index 6156187d15..b142cad13a 100644 --- a/main/install/1.10.0/db_main.sql +++ b/main/install/1.10.0/db_main.sql @@ -2643,18 +2643,18 @@ CREATE TABLE IF NOT EXISTS user_rel_tag ( ); ---DROP TABLE IF EXISTS group_rel_group; ---CREATE TABLE IF NOT EXISTS group_rel_group ( +-- DROP TABLE IF EXISTS group_rel_group; +-- CREATE TABLE IF NOT EXISTS group_rel_group ( -- id int NOT NULL AUTO_INCREMENT, -- group_id int NOT NULL, -- subgroup_id int NOT NULL, -- relation_type int NOT NULL, -- PRIMARY KEY (id) ---); +-- ); ---ALTER TABLE group_rel_group ADD INDEX ( group_id ); ---ALTER TABLE group_rel_group ADD INDEX ( subgroup_id ); ---ALTER TABLE group_rel_group ADD INDEX ( relation_type ); +-- ALTER TABLE group_rel_group ADD INDEX ( group_id ); +-- ALTER TABLE group_rel_group ADD INDEX ( subgroup_id ); +-- ALTER TABLE group_rel_group ADD INDEX ( relation_type ); DROP TABLE IF EXISTS announcement_rel_group; CREATE TABLE IF NOT EXISTS announcement_rel_group ( @@ -2663,6 +2663,7 @@ CREATE TABLE IF NOT EXISTS announcement_rel_group ( announcement_id int NOT NULL, PRIMARY KEY (id) ); + -- -- Table structure for table message attachment -- @@ -3263,7 +3264,7 @@ CREATE TABLE track_e_links ( links_cours_id varchar(40) NOT NULL default '' , links_link_id int NOT NULL default 0, links_session_id INT NOT NULL DEFAULT 0, - PRIMARY KEY (links_id), + PRIMARY KEY (links_id), KEY links_cours_id (links_cours_id), KEY links_user_id (links_user_id) ); @@ -3275,7 +3276,7 @@ CREATE TABLE track_e_login ( login_date datetime NOT NULL default '0000-00-00 00:00:00', login_ip varchar(39) NOT NULL default '', logout_date datetime NULL default NULL, - PRIMARY KEY (login_id), + PRIMARY KEY (login_id), KEY login_user_id (login_user_id) ); diff --git a/main/install/1.10.0/migrate-db-1.9.0-1.10.0-pre.sql b/main/install/1.10.0/migrate-db-1.9.0-1.10.0-pre.sql index 2624ab4c39..35cbd91f81 100755 --- a/main/install/1.10.0/migrate-db-1.9.0-1.10.0-pre.sql +++ b/main/install/1.10.0/migrate-db-1.9.0-1.10.0-pre.sql @@ -74,7 +74,7 @@ ALTER TABLE c_item_property ADD INDEX idx_itemprop_id_tool (c_id, tool(8)); ALTER TABLE c_tool_intro MODIFY COLUMN intro_text MEDIUMTEXT NOT NULL; ALTER TABLE c_quiz_answer ADD INDEX idx_quiz_answer_c_q (c_id, question_id); -CREATE TABLE c_quiz_order( id int unsigned NOT NULL auto_increment, c_id int unsigned NOT NULL, session_id int unsigned NOT NULL, exercise_id int NOT NULL, exercise_order INT NOT NULL, PRIMARY KEY (id)); +CREATE TABLE c_quiz_order( iid bigint unsigned NOT NULL auto_increment, c_id int unsigned NOT NULL, session_id int unsigned NOT NULL, exercise_id int NOT NULL, exercise_order INT NOT NULL, PRIMARY KEY (iid)); ALTER TABLE c_quiz_question_rel_category ADD COLUMN id int unsigned NOT NULL; ALTER TABLE c_quiz_question_rel_category DROP PRIMARY KEY; @@ -195,5 +195,12 @@ ALTER TABLE track_e_hotpotatoes ADD COLUMN c_id int unsigned NOT NULL default 0; ALTER TABLE track_e_exercices ADD COLUMN c_id int unsigned NOT NULL default 0; ALTER TABLE track_e_attempt ADD COLUMN c_id int unsigned NOT NULL default 0; +ALTER TABLE c_quiz ADD COLUMN autolaunch int DEFAULT 0; +RENAME TABLE c_quiz_question_category TO c_quiz_category; +ALTER TABLE c_quiz_category ADD COLUMN parent_id int unsigned NOT NULL default 0; + +CREATE TABLE c_quiz_rel_category (iid bigint unsigned NOT NULL auto_increment, c_id INT unsigned default 0, category_id int unsigned NOT NULL, exercise_id int unsigned NOT NULL, count_questions int NOT NULL default 0, PRIMARY KEY(iid)); + + -- Do not move this UPDATE settings_current SET selected_value = '1.10.0.c9a93d7' WHERE variable = 'chamilo_database_version'; \ No newline at end of file diff --git a/main/newscorm/learnpath_functions.inc.php b/main/newscorm/learnpath_functions.inc.php index e4382d78b8..487e531504 100644 --- a/main/newscorm/learnpath_functions.inc.php +++ b/main/newscorm/learnpath_functions.inc.php @@ -1422,7 +1422,8 @@ function export_exercise($item_id) echo $s = "".get_lang('Question')." "; // Call the showQuestion() function from exercise.lib.php. This basically displays the question in a table. - $test .= showQuestion($questionId, false, 'export', $i); + $question_obj = Question::read($questionId); + $test .= showQuestion($question_obj, false, 'export', $i); } // end foreach()