question_pool.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Question Pool
  5. * This script allows administrators to manage questions and add them into their exercises.
  6. * One question can be in several exercises
  7. * @package chamilo.exercise
  8. * @author Olivier Brouckaert
  9. * @author Julio Montoya adding support to query all questions from all session, courses, exercises
  10. * @author Modify by hubert borderiou 2011-10-21 Question's category
  11. */
  12. // name of the language file that needs to be included
  13. use \ChamiloSession as Session;
  14. $language_file = 'exercice';
  15. require_once 'exercise.class.php';
  16. require_once 'question.class.php';
  17. require_once 'answer.class.php';
  18. require_once '../inc/global.inc.php';
  19. require_once 'exercise.lib.php';
  20. $this_section = SECTION_COURSES;
  21. $is_allowedToEdit = api_is_allowed_to_edit(null,true);
  22. $delete = isset($_GET['delete']) ? intval($_GET['delete']) : null;
  23. $recup = isset($_GET['recup']) ? intval($_GET['recup']) : null;
  24. $fromExercise = isset($_REQUEST['fromExercise']) ? intval($_REQUEST['fromExercise']) : null;
  25. $exerciseId = isset($_REQUEST['exerciseId']) ? intval($_REQUEST['exerciseId']) : null;
  26. $courseCategoryId = isset($_REQUEST['courseCategoryId']) ? intval($_REQUEST['courseCategoryId']) : null;
  27. $exerciseLevel = isset($_REQUEST['exerciseLevel']) ? intval($_REQUEST['exerciseLevel']) : -1;
  28. $answerType = isset($_REQUEST['answerType']) ? intval($_REQUEST['answerType']) : null;
  29. $page = isset($_REQUEST['page']) ? intval($_REQUEST['page']) : 0;
  30. $copy_question = isset($_REQUEST['copy_question']) ? intval($_REQUEST['copy_question']) : 0;
  31. $session_id = isset($_REQUEST['session_id']) ? intval($_REQUEST['session_id']) : null;
  32. $selected_course = isset($_GET['selected_course']) ? intval($_GET['selected_course']) : null;
  33. // save the id of the previous course selected by user to reset menu if we detect that user change course hub 13-10-2011
  34. $course_id_changed = isset($_GET['course_id_changed']) ? intval($_GET['course_id_changed']) : null;
  35. // save the id of the previous exercice selected by user to reset menu if we detect that user change course hub 13-10-2011
  36. $exercice_id_changed = isset($_GET['exercice_id_changed']) ? intval($_GET['exercice_id_changed']) : null;
  37. // by default when we go to the page for the first time, we select the current course
  38. if (!isset($_GET['selected_course']) && !isset($_GET['exerciseId'])) {
  39. $selected_course = api_get_course_int_id();
  40. }
  41. // document path
  42. $documentPath = api_get_path(SYS_COURSE_PATH).$_course['path'].'/document';
  43. // picture path
  44. $picturePath = $documentPath.'/images';
  45. if (empty($objExercise) && !empty($fromExercise)) {
  46. $objExercise = new Exercise();
  47. $objExercise->read($fromExercise);
  48. }
  49. $nameTools = get_lang('QuestionPool');
  50. $interbreadcrumb[] = array("url" => "exercice.php","name" => get_lang('Exercices'));
  51. if (!empty($objExercise)) {
  52. $interbreadcrumb[] = array("url" => "admin.php?exerciseId=".$objExercise->id, "name" => $objExercise->name);
  53. }
  54. // message to be displayed if actions succesful
  55. $displayMessage = "";
  56. if ($is_allowedToEdit) {
  57. //Duplicating a Question
  58. if (!isset($_POST['recup']) && $copy_question != 0 && isset($fromExercise)) {
  59. $origin_course_id = intval($_GET['course_id']);
  60. $origin_course_info = api_get_course_info_by_id($origin_course_id);
  61. $current_course = api_get_course_info();
  62. $old_question_id = $copy_question;
  63. //Reading the source question
  64. $old_question_obj = Question::read($old_question_id, $origin_course_id);
  65. $courseId = $current_course['real_id'];
  66. if ($old_question_obj) {
  67. $old_question_obj->updateTitle($old_question_obj->selectTitle().' - '.get_lang('Copy'));
  68. //Duplicating the source question, in the current course
  69. $new_id = $old_question_obj->duplicate($current_course);
  70. //Reading new question
  71. $new_question_obj = Question::read($new_id);
  72. $new_question_obj->addToList($fromExercise);
  73. //Reading Answers obj of the current course
  74. $new_answer_obj = new Answer($old_question_id, $origin_course_id);
  75. $new_answer_obj->read();
  76. //Duplicating the Answers in the current course
  77. $new_answer_obj->duplicate($new_id, $current_course);
  78. // destruction of the Question object
  79. unset($new_question_obj);
  80. unset($old_question_obj);
  81. $objExercise = new Exercise($courseId);
  82. $objExercise->read($fromExercise);
  83. Session::write('objExercise', $objExercise);
  84. }
  85. $displayMessage = get_lang('ItemAdded');
  86. }
  87. // deletes a question from the database and all exercises
  88. if ($delete) {
  89. // Construction of the Question object
  90. $objQuestionTmp = Question::read($delete);
  91. // if the question exists
  92. if ($objQuestionTmp) {
  93. // deletes the question from all exercises
  94. $objQuestionTmp->delete();
  95. }
  96. // destruction of the Question object
  97. unset($objQuestionTmp);
  98. } elseif($recup && $fromExercise) {
  99. // gets an existing question and copies it into a new exercise
  100. $objQuestionTmp = Question :: read($recup);
  101. // if the question exists
  102. if ($objQuestionTmp) {
  103. // adds the exercise ID represented by $fromExercise into the list of exercises for the current question
  104. $objQuestionTmp->addToList($fromExercise);
  105. }
  106. // destruction of the Question object
  107. unset($objQuestionTmp);
  108. if (!$objExercise instanceOf Exercise) {
  109. $objExercise = new Exercise();
  110. $objExercise->read($fromExercise);
  111. }
  112. // adds the question ID represented by $recup into the list of questions for the current exercise
  113. $objExercise->addToList($recup);
  114. Session::write('objExercise', $objExercise);
  115. // header("Location: admin.php?".api_get_cidreq()."&exerciseId=$fromExercise");
  116. // exit();
  117. } else if( isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) {
  118. $list_recup = $_POST['recup'];
  119. foreach ($list_recup as $course_id => $question_data) {
  120. $origin_course_id = intval($course_id);
  121. $origin_course_info = api_get_course_info_by_id($origin_course_id);
  122. $current_course = api_get_course_info();
  123. foreach ($question_data as $old_question_id) {
  124. //Reading the source question
  125. $old_question_obj = Question::read($old_question_id, $origin_course_id);
  126. if ($old_question_obj) {
  127. $old_question_obj->updateTitle($old_question_obj->selectTitle().' - '.get_lang('Copy'));
  128. //Duplicating the source question, in the current course
  129. $new_id = $old_question_obj->duplicate($current_course);
  130. //Reading new question
  131. $new_question_obj = Question::read($new_id);
  132. $new_question_obj->addToList($fromExercise);
  133. //Reading Answers obj of the current course
  134. $new_answer_obj = new Answer($old_question_id, $origin_course_id);
  135. $new_answer_obj->read();
  136. //Duplicating the Answers in the current course
  137. $new_answer_obj->duplicate($new_id, $current_course);
  138. // destruction of the Question object
  139. unset($new_question_obj);
  140. unset($old_question_obj);
  141. if (!$objExercise instanceOf Exercise) {
  142. $objExercise = new Exercise();
  143. $objExercise->read($fromExercise);
  144. }
  145. }
  146. }
  147. }
  148. Session::write('objExercise',$objExercise);
  149. }
  150. }
  151. if (isset($_SESSION['gradebook'])){
  152. $gradebook= $_SESSION['gradebook'];
  153. }
  154. if (!empty($gradebook) && $gradebook=='view') {
  155. $interbreadcrumb[]= array ('url' => '../gradebook/'.Security::remove_XSS($_SESSION['gradebook_dest']),'name' => get_lang('ToolGradebook'));
  156. }
  157. // if admin of course
  158. if (!$is_allowedToEdit) {
  159. api_not_allowed(true);
  160. }
  161. $confirmYourChoice = addslashes(api_htmlentities(get_lang('ConfirmYourChoice'),ENT_QUOTES,$charset));
  162. $htmlHeadXtra[] = "
  163. <script>
  164. function submit_form(obj) {
  165. document.question_pool.submit();
  166. }
  167. function mark_course_id_changed() {
  168. $('#course_id_changed').val('1');
  169. }
  170. function mark_exercice_id_changed() {
  171. $('#exercice_id_changed').val('1');
  172. }
  173. function confirm_your_choice() {
  174. return confirm('$confirmYourChoice');
  175. }
  176. </script>";
  177. Display::display_header($nameTools,'Exercise');
  178. // Menu
  179. echo '<div class="actions">';
  180. if (isset($type)) {
  181. $url = api_get_self().'?type=1';
  182. } else {
  183. $url = api_get_self();
  184. }
  185. if (isset($fromExercise) && $fromExercise > 0) {
  186. echo '<a href="admin.php?'.api_get_cidreq().'&exerciseId='.$fromExercise.'">'.Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).'</a>';
  187. $titleAdd = get_lang('AddQuestionToTest');
  188. } else {
  189. echo '<a href="exercice.php?'.api_get_cidReq().'">'.Display::return_icon('back.png', get_lang('BackToExercisesList'),'',ICON_SIZE_MEDIUM).'</a>';
  190. echo "<a href='admin.php?exerciseId=0'>".Display::return_icon('add_question.gif', get_lang('NewQu'), '', 32)."</a>";
  191. $titleAdd = get_lang('ManageAllQuestions');
  192. }
  193. echo '</div>';
  194. if ($displayMessage != "") {
  195. Display::display_confirmation_message($displayMessage);
  196. $displayMessage = "";
  197. }
  198. //Form
  199. echo '<form class="form-horizontal" name="question_pool" method="GET" action="'.$url.'">';
  200. //Title
  201. echo '<legend>'.$nameTools.' - '.$titleAdd.'</legend>';
  202. if (isset($type)) {
  203. echo '<input type="hidden" name="type" value="1">';
  204. }
  205. echo '<input type="hidden" name="fromExercise" value="'.$fromExercise.'">';
  206. // Session list, if sessions are used.
  207. $session_list = SessionManager::get_sessions_by_general_coach(api_get_user_id());
  208. $tabAttrParam = array('class'=>'chzn-select', 'onchange'=>'submit_form(this)'); // when sessions are used
  209. $labelFormRow = get_lang('Session');
  210. $session_select_list = array();
  211. foreach($session_list as $item) {
  212. $session_select_list[$item['id']] = $item['name'];
  213. }
  214. $select_session_html = Display::select('session_id', $session_select_list, $session_id, $tabAttrParam);
  215. echo Display::form_row($labelFormRow, $select_session_html);
  216. // Course list, get course list of session, or for course where user is admin
  217. if (!empty($session_id) && $session_id != '-1') {
  218. $course_list = SessionManager::get_course_list_by_session_id($session_id);
  219. } else {
  220. $course_list = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id());
  221. }
  222. $course_select_list = array();
  223. foreach ($course_list as $item) {
  224. $course_select_list[$item['id']] = "";
  225. if ($item['id'] == api_get_course_int_id()) {
  226. $course_select_list[$item['id']] = ">&nbsp;&nbsp;&nbsp;&nbsp;";
  227. }
  228. $course_select_list[$item['id']] .= $item['title'];
  229. }
  230. $select_course_html = Display::select(
  231. 'selected_course',
  232. $course_select_list,
  233. $selected_course,
  234. array('class'=>'chzn-select','onchange'=>'mark_course_id_changed(); submit_form(this);')
  235. );
  236. echo Display::form_row(get_lang('Course'), $select_course_html);
  237. if (empty($selected_course) || $selected_course == '-1') {
  238. $course_info = api_get_course_info();
  239. reset_menu_exo_lvl_type(); // no course selected, reset menu test / difficult� / type de reponse
  240. }
  241. else {
  242. $course_info = CourseManager::get_course_information_by_id($selected_course);
  243. }
  244. // If course has changed, reset the menu default
  245. if ($course_id_changed) {
  246. reset_menu_exo_lvl_type();
  247. }
  248. $course_id = $course_info['real_id'];
  249. //Redefining table calls
  250. $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  251. $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
  252. $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
  253. $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER);
  254. $TBL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  255. $TBL_COURSE_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  256. // Get course categories for the selected course
  257. // get category list for the course $selected_course
  258. $categoryList = Testcategory::getCategoriesIdAndName($selected_course);
  259. $selectCourseCategory = Display::select(
  260. 'courseCategoryId',
  261. $categoryList,
  262. $courseCategoryId,
  263. array('class'=>'chzn-select','onchange'=>'submit_form(this);'),
  264. false
  265. );
  266. echo Display::form_row(get_lang("QuestionCategory"), $selectCourseCategory);
  267. // Get exercise list for this course
  268. $exercise_list = get_all_exercises_for_course_id($course_info, $session_id, $selected_course, false);
  269. //Exercise List
  270. $my_exercise_list = array();
  271. $my_exercise_list['0'] = get_lang('AllExercises');
  272. $my_exercise_list['-1'] = get_lang('OrphanQuestions');
  273. if (is_array($exercise_list)) {
  274. foreach($exercise_list as $row) {
  275. $my_exercise_list[$row['id']] = "";
  276. if ($row['id'] == $fromExercise && $selected_course == api_get_course_int_id()) {
  277. $my_exercise_list[$row['id']] = ">&nbsp;&nbsp;&nbsp;&nbsp;";
  278. }
  279. $my_exercise_list[$row['id']] .= $row['title'];
  280. }
  281. }
  282. if ($exercice_id_changed == 1) {
  283. reset_menu_lvl_type();
  284. }
  285. $select_exercise_html = Display::select(
  286. 'exerciseId',
  287. $my_exercise_list,
  288. $exerciseId,
  289. array('class'=>'chzn-select','onchange'=>'mark_exercice_id_changed(); submit_form(this);'),
  290. false
  291. );
  292. echo Display::form_row(get_lang('Exercise'), $select_exercise_html);
  293. // Difficulty list (only from 0 to 5)
  294. $select_difficulty_html = Display::select(
  295. 'exerciseLevel',
  296. array(-1 => get_lang('All'), 0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5),
  297. $exerciseLevel,
  298. array('class'=>'chzn-select', 'onchange'=>'submit_form(this);'),
  299. false
  300. );
  301. echo Display::form_row(get_lang('Difficulty'), $select_difficulty_html);
  302. // Answer type
  303. $question_list = Question::get_question_type_list();
  304. $new_question_list = array();
  305. $new_question_list['-1'] = get_lang('All');
  306. $objExercise = new Exercise();
  307. $objExercise->read($fromExercise);
  308. foreach ($question_list as $key=>$item) {
  309. if ($objExercise->feedback_type == EXERCISE_FEEDBACK_TYPE_DIRECT) {
  310. if (!in_array($key, array(HOT_SPOT_DELINEATION, UNIQUE_ANSWER))) {
  311. continue;
  312. }
  313. $new_question_list[$key] = get_lang($item[1]);
  314. } else {
  315. if ($key == HOT_SPOT_DELINEATION) {
  316. continue;
  317. }
  318. $new_question_list[$key] = get_lang($item[1]);
  319. }
  320. }
  321. //Answer type list
  322. $select_answer_html = Display::select('answerType', $new_question_list, $answerType, array('class'=>'chzn-select','onchange'=>'submit_form(this);'), false);
  323. echo Display::form_row(get_lang('AnswerType'), $select_answer_html);
  324. $button = '<button class="save" type="submit" name="name" value="'.get_lang('Filter').'">'.get_lang('Filter').'</button>';
  325. echo Display::form_row('', $button);
  326. echo "<input type='hidden' id='course_id_changed' name='course_id_changed' value='0' />";
  327. echo "<input type='hidden' id='exercice_id_changed' name='exercice_id_changed' value='0' />";
  328. ?>
  329. </form>
  330. <div class="clear"></div>
  331. <form method="post" action="<?php echo $url.'?'.api_get_cidreq().'&fromExercise='.$fromExercise; ?>" >
  332. <?php
  333. echo '<input type="hidden" name="course_id" value="'.$selected_course.'">';
  334. $main_question_list = array();
  335. // if we have selected an exercise in the list-box 'Filter'
  336. if ($exerciseId > 0) {
  337. $where = '';
  338. $from = '';
  339. if (isset($courseCategoryId) && $courseCategoryId > 0) {
  340. $from = ", $TBL_COURSE_REL_CATEGORY crc ";
  341. $where .= " AND crc.c_id=$selected_course AND crc.question_id=qu.id AND crc.category_id=$courseCategoryId";
  342. }
  343. if (isset($exerciseLevel) && $exerciseLevel != -1) {
  344. $where .= ' AND level='.$exerciseLevel;
  345. }
  346. if (isset($answerType) && $answerType > 0) {
  347. $where .= ' AND type='.$answerType;
  348. }
  349. $sql = "SELECT DISTINCT
  350. id,
  351. question,
  352. type,
  353. level
  354. FROM
  355. $TBL_EXERCICE_QUESTION qt,
  356. $TBL_QUESTIONS qu
  357. $from
  358. WHERE
  359. qt.question_id = qu.id
  360. AND qt.exercice_id=$exerciseId
  361. AND qt.c_id=$selected_course
  362. AND qu.c_id=$selected_course
  363. $where
  364. ORDER BY question_order";
  365. $result = Database::query($sql);
  366. while($row = Database::fetch_array($result, 'ASSOC')) {
  367. $main_question_list[] = $row;
  368. }
  369. } elseif ($exerciseId == -1) {
  370. // If we have selected the option 'Orphan questions' in the list-box 'Filter'
  371. $level_where = '';
  372. $from = '';
  373. if (isset($courseCategoryId) && $courseCategoryId > 0) {
  374. $from = ", $TBL_COURSE_REL_CATEGORY crc ";
  375. $level_where .= " AND crc.c_id=$selected_course AND crc.question_id=qu.id AND crc.category_id=$courseCategoryId";
  376. }
  377. if (isset($exerciseLevel) && $exerciseLevel!= -1 ) {
  378. $level_where = ' AND level='.$exerciseLevel;
  379. }
  380. $answer_where = '';
  381. if (isset($answerType) && $answerType >0 -1 ) {
  382. $answer_where = ' AND type='.$answerType;
  383. }
  384. // @todo fix this query with the new id field
  385. $sql = " (
  386. SELECT q.* FROM $TBL_QUESTIONS q INNER JOIN $TBL_EXERCICE_QUESTION r
  387. ON (q.c_id = r.c_id AND q.id = r.question_id)
  388. INNER JOIN $TBL_EXERCICES ex
  389. ON (ex.id = r.exercice_id AND ex.c_id = r.c_id ) $from
  390. WHERE ex.c_id = '$selected_course' AND ex.active = '-1' $level_where $answer_where
  391. )
  392. UNION
  393. (
  394. SELECT q.* FROM $TBL_QUESTIONS q
  395. LEFT OUTER JOIN $TBL_EXERCICE_QUESTION r
  396. ON (q.c_id = r.c_id AND q.id = r.question_id)
  397. WHERE q.c_id = '$selected_course' AND r.question_id is null $level_where $answer_where
  398. )
  399. UNION
  400. (
  401. SELECT q.* FROM $TBL_QUESTIONS q
  402. INNER JOIN $TBL_EXERCICE_QUESTION r
  403. ON (q.c_id = r.c_id AND q.id = r.question_id)
  404. WHERE r.c_id = '$selected_course' AND (r.exercice_id = '-1' OR r.exercice_id = '0') $level_where $answer_where
  405. )";
  406. $result = Database::query($sql);
  407. while($row = Database::fetch_array($result, 'ASSOC')) {
  408. $main_question_list[] = $row;
  409. }
  410. } else {
  411. // All tests for selected course
  412. // If we have not selected any option in the list-box 'Filter'
  413. $filter = '';
  414. $from = '';
  415. if (isset($courseCategoryId) && $courseCategoryId > 0) {
  416. $from = ", $TBL_COURSE_REL_CATEGORY crc ";
  417. $filter .= " AND crc.c_id = $selected_course AND crc.question_id = qu.id AND crc.category_id = $courseCategoryId";
  418. }
  419. if (isset($exerciseLevel) && $exerciseLevel != -1) {
  420. $filter .= ' AND level='.$exerciseLevel.' ';
  421. }
  422. if (isset($answerType) && $answerType > 0) {
  423. $filter .= ' AND qu.type='.$answerType.' ';
  424. }
  425. if (!empty($session_id) && $session_id != '-1') {
  426. $main_question_list = array();
  427. if (!empty($course_list)) {
  428. foreach ($course_list as $course_item) {
  429. if (!empty($selected_course) && $selected_course != '-1') {
  430. if ($selected_course != $course_item['id']) {
  431. continue;
  432. }
  433. }
  434. $exercise_list = get_all_exercises($course_item, $session_id);
  435. if (!empty($exercise_list)) {
  436. foreach ($exercise_list as $exercise) {
  437. $my_exercise = new Exercise($course_item['id']);
  438. $my_exercise->read($exercise['id']);
  439. if (!empty($my_exercise)) {
  440. if (!empty($my_exercise->questionList)) {
  441. foreach ($my_exercise->questionList as $question_id) {
  442. $question_obj = Question::read(
  443. $question_id,
  444. $course_item['id']
  445. );
  446. if ($exerciseLevel != '-1') {
  447. if ($exerciseLevel != $question_obj->level) {
  448. continue;
  449. }
  450. }
  451. if ($answerType > 0) {
  452. if ($answerType != $question_obj->type) {
  453. continue;
  454. }
  455. }
  456. if ($courseCategoryId > 0 && Testcategory::getCategoryForQuestion(
  457. $question_obj->id,
  458. $selected_course
  459. )
  460. ) {
  461. continue;
  462. }
  463. if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_DIRECT) {
  464. if ($question_obj->type == HOT_SPOT_DELINEATION) {
  465. continue;
  466. }
  467. }
  468. $question_row = array(
  469. 'id' => $question_obj->id,
  470. 'question' => $question_obj->question,
  471. 'type' => $question_obj->type,
  472. 'level' => $question_obj->level,
  473. 'exercise_id' => $exercise['id'],
  474. 'course_id' => $course_item['id'],
  475. );
  476. $main_question_list[] = $question_row;
  477. }
  478. }
  479. }
  480. }
  481. }
  482. }
  483. }
  484. } else {
  485. if ($session_id == -1 or empty($session_id)) {
  486. $session_id = 0;
  487. }
  488. // All tests for the course selected, not in session
  489. $sql = "SELECT DISTINCT qu.id, question, qu.type, level, q.session_id
  490. FROM $TBL_QUESTIONS as qu, $TBL_EXERCICE_QUESTION as qt, $TBL_EXERCICES as q $from
  491. WHERE
  492. qu.c_id = $selected_course AND
  493. qt.c_id = $selected_course AND
  494. q.c_id = $selected_course AND
  495. qu.id = qt.question_id AND
  496. q.session_id = $session_id AND
  497. q.id = qt.exercice_id $filter
  498. ORDER BY session_id ASC";
  499. $result = Database::query($sql);
  500. while ($row = Database::fetch_array($result, 'ASSOC')) {
  501. $main_question_list[] = $row;
  502. }
  503. }
  504. // forces the value to 0
  505. $exerciseId=0;
  506. }
  507. $nbrQuestions = count($main_question_list);
  508. // build the line of the array to display questions
  509. // Actions are different if you launch the question_pool page
  510. // They are different too if you have displayed questions from your course
  511. // Or from another course you are the admin(or session admin)
  512. // from a test or not
  513. /*
  514. +--------------------------------------------+--------------------------------------------+
  515. | NOT IN A TEST | IN A TEST |
  516. +----------------------+---------------------+---------------------+----------------------+
  517. |IN THE COURSE (*) "x | NOT IN THE COURSE o | IN THE COURSE + | NOT IN THE COURSE o |
  518. +----------------------+---------------------+---------------------+----------------------+
  519. |Edit the question | Do nothing | Add question to test|Clone question in test|
  520. |Delete the question | | | |
  521. |(true delete) | | | |
  522. +----------------------+---------------------+---------------------+----------------------+
  523. (*) this is the only way to delete or modify orphan questions
  524. */
  525. //
  526. if ($fromExercise <= 0) { // NOT IN A TEST - IN THE COURSE
  527. if ($selected_course == api_get_course_int_id()) {
  528. $actionLabel = get_lang('Modify');
  529. $actionIcon1 = "edit";
  530. $actionIcon2 = "delete";
  531. $questionTagA = 1; // we are in the course, question title can be a link to the question edit page
  532. } else { // NOT IN A TEST - NOT IN THE COURSE
  533. $actionLabel = get_lang('Reuse');
  534. $actionIcon1 = get_lang('MustBeInATest');
  535. $actionIcon2 = "";
  536. $questionTagA = 0; // we are not in this course, to messy if we link to the question in another course
  537. }
  538. } else { // IN A TEST - IN THE COURSE
  539. if ($selected_course == api_get_course_int_id()) {
  540. $actionLabel = get_lang('Reuse');
  541. $actionIcon1 = "add";
  542. $actionIcon2 = "";
  543. $questionTagA = 1;
  544. } else { // IN A TEST - NOT IN THE COURSE
  545. $actionLabel = get_lang('Reuse');
  546. $actionIcon1 = "clone";
  547. $actionIcon2 = "";
  548. $questionTagA = 0;
  549. }
  550. }
  551. // Display table
  552. $header = array();
  553. $header[] = array(get_lang('QuestionUpperCaseFirstLetter'), false, array("style"=>"text-align:center"), '');
  554. $header[] = array(get_lang('Type'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), '');
  555. $header[] = array(get_lang('QuestionCategory'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), '');
  556. $header[] = array(get_lang('Difficulty'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), '');
  557. $header[] = array($actionLabel, false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), '');
  558. $data = array();
  559. if (is_array($main_question_list)) {
  560. foreach ($main_question_list as $tabQuestion) {
  561. $row = array();
  562. // This function checks if the question can be read
  563. $question_type = get_question_type_for_question($selected_course, $tabQuestion['id']);
  564. if (empty($question_type)) {
  565. continue;
  566. }
  567. $sessionId = isset($tabQuestion['session_id']) ? $tabQuestion['session_id'] : null;
  568. $row[] = get_a_tag_for_question(
  569. $questionTagA,
  570. $fromExercise,
  571. $tabQuestion['id'],
  572. $tabQuestion['type'],
  573. $tabQuestion['question'],
  574. $sessionId
  575. );
  576. $row[] = $question_type;
  577. $row[] = get_question_categorie_for_question($selected_course, $tabQuestion['id']);
  578. $row[] = $tabQuestion['level'];
  579. $row[] = get_action_icon_for_question(
  580. $actionIcon1,
  581. $fromExercise,
  582. $tabQuestion['id'],
  583. $tabQuestion['type'],
  584. $tabQuestion['question'],
  585. $selected_course,
  586. $courseCategoryId,
  587. $exerciseLevel,
  588. $answerType,
  589. $session_id,
  590. $exerciseId
  591. ).
  592. "&nbsp;".
  593. get_action_icon_for_question(
  594. $actionIcon2,
  595. $fromExercise,
  596. $tabQuestion['id'],
  597. $tabQuestion['type'],
  598. $tabQuestion['question'],
  599. $selected_course,
  600. $courseCategoryId,
  601. $exerciseLevel,
  602. $answerType,
  603. $session_id,
  604. $exerciseId
  605. );
  606. $data[] = $row;
  607. }
  608. }
  609. Display :: display_sortable_table(
  610. $header,
  611. $data,
  612. '',
  613. array('per_page_default' => 999, 'per_page' => 999, 'page_nr' => 1)
  614. );
  615. if (!$nbrQuestions) {
  616. echo get_lang('NoQuestion');
  617. }
  618. // The (+) system as now make this button useless
  619. // Hubert Borderiou 27-10-2011
  620. //if (api_get_session_id() == 0){
  621. // echo '<div style="width:100%; border-top:1px dotted #4171B5;"><button class="save" type="submit">'.get_lang('Reuse').'</button></div></form>';
  622. //}
  623. Display::display_footer();
  624. // Some functions here, just for question_pool to ease the code
  625. /*
  626. Put the menu entry for level and type to default "Choice"
  627. It is useful if you change the exercise, you need to reset the other menus
  628. hubert.borderiou 13-10-2011
  629. */
  630. function reset_menu_lvl_type() {
  631. global $exerciseLevel, $answerType;
  632. $answerType = -1;
  633. $exerciseLevel = -1;
  634. }
  635. /*
  636. Put the menu entry for exercise and level and type to default "Choice"
  637. It is useful if you change the course, you need to reset the other menus
  638. hubert.borderiou 13-10-2011
  639. */
  640. function reset_menu_exo_lvl_type() {
  641. global $exerciseId, $courseCategoryId;
  642. reset_menu_lvl_type();
  643. $exerciseId = 0;
  644. $courseCategoryId = 0;
  645. }
  646. /**
  647. * return the <a> link to admin question, if needed
  648. * @param int $in_addA
  649. * @param int $in_fromex
  650. * @param int $in_questionid
  651. * @param int $in_questiontype
  652. * @param string $in_questionname
  653. * @param int $sessionId
  654. * @return string
  655. * @author hubert.borderiou
  656. */
  657. function get_a_tag_for_question(
  658. $in_addA,
  659. $in_fromex,
  660. $in_questionid,
  661. $in_questiontype,
  662. $in_questionname,
  663. $sessionId
  664. ) {
  665. $res = $in_questionname;
  666. $sessionIcon = null;
  667. if ($in_addA) {
  668. if (!empty($sessionId)) {
  669. $sessionIcon = ' '.Display::return_icon('star.png', get_lang('Session'));
  670. }
  671. $res = "<a href='admin.php?".api_get_cidreq()."&editQuestion=$in_questionid&type=$in_questiontype&fromExercise=$in_fromex'>".
  672. $res.$sessionIcon.
  673. "</a>";
  674. }
  675. return $res;
  676. }
  677. /*
  678. $row[] = get_action_icon_for_question(
  679. $actionIcon1, --
  680. $fromExercise, --
  681. $tabQuestion['id'], --
  682. $tabQuestion['type'],
  683. $tabQuestion['question'],
  684. $selected_course,
  685. $courseCategoryId,
  686. $exerciseLevel,
  687. $answerType,
  688. $session_id,
  689. $exerciseId).
  690. "&nbsp;".
  691. get_action_icon_for_question($actionIcon2, $fromExercise, $tabQuestion['id'], $tabQuestion['type'],
  692. $tabQuestion['question'], $selected_course, $courseCategoryId, $exerciseLevel, $answerType,
  693. $session_id, $exerciseId);
  694. */
  695. /*
  696. Return the <a> html code for delete, add, clone, edit a question
  697. in_action = the code of the action triggered by the button
  698. from_exercice = the id of the current exercice from which we click on question pool
  699. in_questionid = the id of the current question
  700. in_questiontype = the code of the type of the current question
  701. in_questionname = the name of the question
  702. in_selected_course = the if of the course chosen in the FILTERING MENU
  703. in_courseCategoryId = the id of the category chosen in the FILTERING MENU
  704. in_exerciseLevel = the level of the exercice chosen in the FILTERING MENU
  705. in_answerType = the code of the type of the question chosen in the FILTERING MENU
  706. in_session_id = the id of the session_id chosen in the FILTERING MENU
  707. in_exercice_id = the id of the exercice chosen in the FILTERING MENU
  708. */
  709. function get_action_icon_for_question(
  710. $in_action,
  711. $from_exercice,
  712. $in_questionid,
  713. $in_questiontype,
  714. $in_questionname,
  715. $in_selected_course,
  716. $in_courseCategoryId,
  717. $in_exerciseLevel,
  718. $in_answerType,
  719. $in_session_id,
  720. $in_exercice_id
  721. ) {
  722. $res = "";
  723. $getParams = "&selected_course=$in_selected_course&courseCategoryId=$in_courseCategoryId&exerciseId=$in_exercice_id&exerciseLevel=$in_exerciseLevel&answerType=$in_answerType&session_id=$in_session_id";
  724. switch ($in_action) {
  725. case "delete" :
  726. $res = "<a href='".api_get_self()."?".api_get_cidreq().$getParams."&delete=$in_questionid' onclick='return confirm_your_choice()'>";
  727. $res .= Display::return_icon("delete.png", get_lang('Delete'));
  728. $res .= "</a>";
  729. break;
  730. case "edit" :
  731. $res = get_a_tag_for_question(
  732. 1,
  733. $from_exercice,
  734. $in_questionid,
  735. $in_questiontype,
  736. Display::return_icon("edit.png", get_lang('Modify')),
  737. $in_session_id
  738. );
  739. break;
  740. case "add":
  741. // add if question is not already in test
  742. $myObjEx = new Exercise();
  743. $myObjEx->read($from_exercice);
  744. if (!$myObjEx->isInList($in_questionid)) {
  745. $res = "<a href='".api_get_self()."?".api_get_cidreq().$getParams."&recup=$in_questionid&fromExercise=$from_exercice'>";
  746. $res .= Display::return_icon("view_more_stats.gif", get_lang('InsertALinkToThisQuestionInTheExercise'));
  747. $res .= "</a>";
  748. } else {
  749. $res = "-";
  750. }
  751. unset($myObjEx);
  752. break;
  753. case "clone":
  754. $url = api_get_self()."?".api_get_cidreq().$getParams."&amp;copy_question=$in_questionid&amp;course_id=$in_selected_course&amp;fromExercise=$from_exercice";
  755. $res = Display::url(
  756. Display::return_icon('cd.gif', get_lang('ReUseACopyInCurrentTest')),
  757. $url
  758. );
  759. break;
  760. default :
  761. $res = $in_action;
  762. break;
  763. }
  764. return $res;
  765. }
  766. /**
  767. * Return the icon for the question type
  768. * @author hubert.borderiou 13-10-2011
  769. */
  770. function get_question_type_for_question($in_selectedcourse, $in_questionid)
  771. {
  772. $myObjQuestion = Question::read($in_questionid, $in_selectedcourse);
  773. $questionType = null;
  774. if (!empty($myObjQuestion)) {
  775. list($typeImg, $typeExpl) = $myObjQuestion->get_type_icon_html();
  776. $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array());
  777. unset($myObjQuestion);
  778. }
  779. return $questionType;
  780. }
  781. // return the name of the category for the question in a course
  782. // hubert.borderiou 13-10-2011
  783. function get_question_categorie_for_question($in_courseid, $in_questionid)
  784. {
  785. $cat = Testcategory::getCategoryNameForQuestion($in_questionid, $in_courseid);
  786. return $cat;
  787. }