question_pool.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  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. $_course = api_get_course_info();
  42. if (empty($objExercise) && !empty($fromExercise)) {
  43. $objExercise = new Exercise();
  44. $objExercise->read($fromExercise);
  45. }
  46. $nameTools = get_lang('QuestionPool');
  47. $interbreadcrumb[] = array("url" => "exercice.php","name" => get_lang('Exercices'));
  48. if (!empty($objExercise)) {
  49. $interbreadcrumb[] = array("url" => "admin.php?exerciseId=".$objExercise->id, "name" => $objExercise->name);
  50. }
  51. // message to be displayed if actions successful
  52. $displayMessage = "";
  53. if ($is_allowedToEdit) {
  54. // Duplicating a Question
  55. if (!isset($_POST['recup']) && $copy_question != 0 && isset($fromExercise)) {
  56. $origin_course_id = intval($_GET['course_id']);
  57. $origin_course_info = api_get_course_info_by_id($origin_course_id);
  58. $current_course = api_get_course_info();
  59. $old_question_id = $copy_question;
  60. // Reading the source question
  61. $old_question_obj = Question::read($old_question_id, $origin_course_id);
  62. $courseId = $current_course['real_id'];
  63. if ($old_question_obj) {
  64. $old_question_obj->updateTitle(
  65. $old_question_obj->selectTitle() . ' - ' . get_lang('Copy')
  66. );
  67. //Duplicating the source question, in the current course
  68. $new_id = $old_question_obj->duplicate($current_course);
  69. //Reading new question
  70. $new_question_obj = Question::read($new_id);
  71. $new_question_obj->addToList($fromExercise);
  72. //Reading Answers obj of the current course
  73. $new_answer_obj = new Answer($old_question_id, $origin_course_id);
  74. $new_answer_obj->read();
  75. //Duplicating the Answers in the current course
  76. $new_answer_obj->duplicate($new_id, $current_course);
  77. // destruction of the Question object
  78. unset($new_question_obj);
  79. unset($old_question_obj);
  80. $objExercise = new Exercise($courseId);
  81. $objExercise->read($fromExercise);
  82. Session::write('objExercise', $objExercise);
  83. }
  84. $displayMessage = get_lang('ItemAdded');
  85. }
  86. // Deletes a question from the database and all exercises
  87. if ($delete) {
  88. // Construction of the Question object
  89. $objQuestionTmp = Question::read($delete);
  90. // if the question exists
  91. if ($objQuestionTmp) {
  92. // deletes the question from all exercises
  93. $objQuestionTmp->delete();
  94. }
  95. // destruction of the Question object
  96. unset($objQuestionTmp);
  97. } elseif($recup && $fromExercise) {
  98. // gets an existing question and copies it into a new exercise
  99. $objQuestionTmp = Question :: read($recup);
  100. // if the question exists
  101. if ($objQuestionTmp) {
  102. /* Adds the exercise ID represented by $fromExercise into the list
  103. 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. } else if (isset($_POST['recup']) && is_array($_POST['recup']) && $fromExercise) {
  116. $list_recup = $_POST['recup'];
  117. foreach ($list_recup as $course_id => $question_data) {
  118. $origin_course_id = intval($course_id);
  119. $origin_course_info = api_get_course_info_by_id($origin_course_id);
  120. $current_course = api_get_course_info();
  121. foreach ($question_data as $old_question_id) {
  122. //Reading the source question
  123. $old_question_obj = Question::read($old_question_id, $origin_course_id);
  124. if ($old_question_obj) {
  125. $old_question_obj->updateTitle(
  126. $old_question_obj->selectTitle() . ' - ' . get_lang('Copy')
  127. );
  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.'">'.
  187. Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).'</a>';
  188. $titleAdd = get_lang('AddQuestionToTest');
  189. } else {
  190. echo '<a href="exercice.php?'.api_get_cidReq().'">'.
  191. Display::return_icon('back.png', get_lang('BackToExercisesList'),'',ICON_SIZE_MEDIUM).'</a>';
  192. echo "<a href='admin.php?exerciseId=0'>".Display::return_icon('add_question.gif', get_lang('NewQu'), '', ICON_SIZE_MEDIUM)."</a>";
  193. $titleAdd = get_lang('ManageAllQuestions');
  194. }
  195. echo '</div>';
  196. if ($displayMessage != "") {
  197. Display::display_confirmation_message($displayMessage);
  198. $displayMessage = "";
  199. }
  200. // Form
  201. echo '<form class="form-horizontal" name="question_pool" method="GET" action="'.$url.'">';
  202. // Title
  203. echo '<legend>'.$nameTools.' - '.$titleAdd.'</legend>';
  204. if (isset($type)) {
  205. echo '<input type="hidden" name="type" value="1">';
  206. }
  207. echo '<input type="hidden" name="fromExercise" value="'.$fromExercise.'">';
  208. // Session list, if sessions are used.
  209. $sessionList = SessionManager::get_sessions_by_user(api_get_user_id(), api_is_platform_admin());
  210. $tabAttrParam = array('class'=>'chzn-select', 'onchange'=>'submit_form(this)');
  211. $labelFormRow = get_lang('Session');
  212. $session_select_list = array();
  213. foreach ($sessionList as $item) {
  214. $session_select_list[$item['session_id']] = $item['session_name'];
  215. }
  216. $select_session_html = Display::select('session_id', $session_select_list, $session_id, $tabAttrParam);
  217. echo Display::form_row($labelFormRow, $select_session_html);
  218. // Course list, get course list of session, or for course where user is admin
  219. if (!empty($session_id) && $session_id != '-1' && !empty($sessionList)) {
  220. $sessionInfo = array();
  221. foreach ($sessionList as $session) {
  222. if ($session['session_id'] == $session_id) {
  223. $sessionInfo = $session;
  224. }
  225. }
  226. $course_list = $sessionInfo['courses'];
  227. } else {
  228. $course_list = CourseManager::get_course_list_of_user_as_course_admin(
  229. api_get_user_id()
  230. );
  231. // Admin fix, add the current course in the question pool.
  232. if (api_is_platform_admin()) {
  233. $courseInfo = api_get_course_info();
  234. if (!empty($course_list)) {
  235. $courseIdList = array_keys($course_list);
  236. if (!in_array($courseInfo['real_id'], $courseIdList)) {
  237. $course_list = array_merge($course_list, array($courseInfo));
  238. }
  239. } else {
  240. $course_list = array($courseInfo);
  241. }
  242. }
  243. }
  244. $course_select_list = array();
  245. foreach ($course_list as $item) {
  246. $courseItemId = $item['real_id'];
  247. $courseInfo = api_get_course_info_by_id($courseItemId);
  248. $course_select_list[$courseItemId] = "";
  249. if ($courseItemId == api_get_course_int_id()) {
  250. $course_select_list[$courseItemId] = ">&nbsp;&nbsp;&nbsp;&nbsp;";
  251. }
  252. $course_select_list[$courseItemId] .= $courseInfo['title'];
  253. }
  254. $select_course_html = Display::select(
  255. 'selected_course',
  256. $course_select_list,
  257. $selected_course,
  258. array('class'=>'chzn-select','onchange'=>'mark_course_id_changed(); submit_form(this);')
  259. );
  260. echo Display::form_row(get_lang('Course'), $select_course_html);
  261. if (empty($selected_course) || $selected_course == '-1') {
  262. $course_info = api_get_course_info();
  263. // no course selected, reset menu test / difficult� / type de reponse
  264. reset_menu_exo_lvl_type();
  265. } else {
  266. $course_info = CourseManager::get_course_information_by_id($selected_course);
  267. }
  268. // If course has changed, reset the menu default
  269. if ($course_id_changed) {
  270. reset_menu_exo_lvl_type();
  271. }
  272. $course_id = $course_info['real_id'];
  273. // Redefining table calls
  274. $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  275. $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
  276. $TBL_QUESTIONS = Database::get_course_table(TABLE_QUIZ_QUESTION);
  277. $TBL_REPONSES = Database::get_course_table(TABLE_QUIZ_ANSWER);
  278. $TBL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  279. $TBL_COURSE_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  280. // Get course categories for the selected course
  281. // get category list for the course $selected_course
  282. $categoryList = Testcategory::getCategoriesIdAndName($selected_course);
  283. $selectCourseCategory = Display::select(
  284. 'courseCategoryId',
  285. $categoryList,
  286. $courseCategoryId,
  287. array('class'=>'chzn-select','onchange'=>'submit_form(this);'),
  288. false
  289. );
  290. echo Display::form_row(get_lang("QuestionCategory"), $selectCourseCategory);
  291. // Get exercise list for this course
  292. $exercise_list = get_all_exercises_for_course_id(
  293. $course_info,
  294. $session_id,
  295. $selected_course,
  296. false
  297. );
  298. //Exercise List
  299. $my_exercise_list = array();
  300. $my_exercise_list['0'] = get_lang('AllExercises');
  301. $my_exercise_list['-1'] = get_lang('OrphanQuestions');
  302. if (is_array($exercise_list)) {
  303. foreach($exercise_list as $row) {
  304. $my_exercise_list[$row['id']] = "";
  305. if ($row['id'] == $fromExercise && $selected_course == api_get_course_int_id()) {
  306. $my_exercise_list[$row['id']] = ">&nbsp;&nbsp;&nbsp;&nbsp;";
  307. }
  308. $my_exercise_list[$row['id']] .= $row['title'];
  309. }
  310. }
  311. if ($exercice_id_changed == 1) {
  312. reset_menu_lvl_type();
  313. }
  314. $select_exercise_html = Display::select(
  315. 'exerciseId',
  316. $my_exercise_list,
  317. $exerciseId,
  318. array('class'=>'chzn-select','onchange'=>'mark_exercice_id_changed(); submit_form(this);'),
  319. false
  320. );
  321. echo Display::form_row(get_lang('Exercise'), $select_exercise_html);
  322. // Difficulty list (only from 0 to 5)
  323. $levels = array(
  324. -1 => get_lang('All'),
  325. 0 => 0,
  326. 1 => 1,
  327. 2 => 2,
  328. 3 => 3,
  329. 4 => 4,
  330. 5 => 5
  331. );
  332. $select_difficulty_html = Display::select(
  333. 'exerciseLevel',
  334. $levels,
  335. $exerciseLevel,
  336. array('class'=>'chzn-select', 'onchange'=>'submit_form(this);'),
  337. false
  338. );
  339. echo Display::form_row(get_lang('Difficulty'), $select_difficulty_html);
  340. // Answer type
  341. $question_list = Question::get_question_type_list();
  342. $new_question_list = array();
  343. $new_question_list['-1'] = get_lang('All');
  344. if (!empty($_course)) {
  345. $objExercise = new Exercise();
  346. $objExercise->read($fromExercise);
  347. foreach ($question_list as $key => $item) {
  348. if ($objExercise->feedback_type == EXERCISE_FEEDBACK_TYPE_DIRECT) {
  349. if (!in_array($key, array(HOT_SPOT_DELINEATION, UNIQUE_ANSWER))) {
  350. continue;
  351. }
  352. $new_question_list[$key] = get_lang($item[1]);
  353. } else {
  354. if ($key == HOT_SPOT_DELINEATION) {
  355. continue;
  356. }
  357. $new_question_list[$key] = get_lang($item[1]);
  358. }
  359. }
  360. }
  361. // Answer type list
  362. $select_answer_html = Display::select(
  363. 'answerType',
  364. $new_question_list,
  365. $answerType,
  366. array('class'=>'chzn-select','onchange'=>'submit_form(this);'),
  367. false
  368. );
  369. echo Display::form_row(get_lang('AnswerType'), $select_answer_html);
  370. $button = '<button class="save" type="submit" name="name" value="'.get_lang('Filter').'">'.get_lang('Filter').'</button>';
  371. echo Display::form_row('', $button);
  372. echo "<input type='hidden' id='course_id_changed' name='course_id_changed' value='0' />";
  373. echo "<input type='hidden' id='exercice_id_changed' name='exercice_id_changed' value='0' />";
  374. ?>
  375. </form>
  376. <div class="clear"></div>
  377. <form method="post" action="<?php echo $url.'?'.api_get_cidreq().'&fromExercise='.$fromExercise; ?>" >
  378. <?php
  379. echo '<input type="hidden" name="course_id" value="'.$selected_course.'">';
  380. $mainQuestionList = array();
  381. // if we have selected an exercise in the list-box 'Filter'
  382. if ($exerciseId > 0) {
  383. $where = '';
  384. $from = '';
  385. if (isset($courseCategoryId) && $courseCategoryId > 0) {
  386. $from = ", $TBL_COURSE_REL_CATEGORY crc ";
  387. $where .= " AND crc.c_id=$selected_course AND crc.question_id=qu.id AND crc.category_id=$courseCategoryId";
  388. }
  389. if (isset($exerciseLevel) && $exerciseLevel != -1) {
  390. $where .= ' AND level='.$exerciseLevel;
  391. }
  392. if (isset($answerType) && $answerType > 0) {
  393. $where .= ' AND type='.$answerType;
  394. }
  395. $sql = "SELECT DISTINCT
  396. id,
  397. question,
  398. type,
  399. level
  400. FROM
  401. $TBL_EXERCICE_QUESTION qt,
  402. $TBL_QUESTIONS qu
  403. $from
  404. WHERE
  405. qt.question_id = qu.id
  406. AND qt.exercice_id=$exerciseId
  407. AND qt.c_id=$selected_course
  408. AND qu.c_id=$selected_course
  409. $where
  410. ORDER BY question_order";
  411. $result = Database::query($sql);
  412. while($row = Database::fetch_array($result, 'ASSOC')) {
  413. $mainQuestionList[] = $row;
  414. }
  415. } elseif ($exerciseId == -1) {
  416. // If we have selected the option 'Orphan questions' in the list-box 'Filter'
  417. $level_where = '';
  418. $from = '';
  419. if (isset($courseCategoryId) && $courseCategoryId > 0) {
  420. $from = " INNER JOIN $TBL_COURSE_REL_CATEGORY crc ON crc.question_id=q.id AND crc.c_id= q.c_id ";
  421. $level_where .= " AND
  422. crc.c_id = $selected_course AND
  423. crc.category_id = $courseCategoryId";
  424. }
  425. if (isset($exerciseLevel) && $exerciseLevel!= -1 ) {
  426. $level_where = ' AND level='.$exerciseLevel;
  427. }
  428. $answer_where = '';
  429. if (isset($answerType) && $answerType >0 -1 ) {
  430. $answer_where = ' AND type='.$answerType;
  431. }
  432. // @todo fix this query with the new id field
  433. $sql = " (
  434. SELECT q.* FROM $TBL_QUESTIONS q
  435. INNER JOIN $TBL_EXERCICE_QUESTION r
  436. ON (q.c_id = r.c_id AND q.id = r.question_id)
  437. INNER JOIN $TBL_EXERCICES ex
  438. ON (ex.id = r.exercice_id AND ex.c_id = r.c_id )
  439. $from
  440. WHERE
  441. ex.c_id = '$selected_course' AND
  442. ex.active = '-1'
  443. $level_where $answer_where
  444. )
  445. UNION
  446. (
  447. SELECT q.* FROM $TBL_QUESTIONS q
  448. LEFT OUTER JOIN $TBL_EXERCICE_QUESTION r
  449. ON (q.c_id = r.c_id AND q.id = r.question_id)
  450. $from
  451. WHERE
  452. q.c_id = '$selected_course' AND
  453. r.question_id is null
  454. $level_where $answer_where
  455. )
  456. UNION
  457. (
  458. SELECT q.* FROM $TBL_QUESTIONS q
  459. INNER JOIN $TBL_EXERCICE_QUESTION r
  460. ON (q.c_id = r.c_id AND q.id = r.question_id)
  461. $from
  462. WHERE
  463. r.c_id = '$selected_course' AND
  464. (r.exercice_id = '-1' OR r.exercice_id = '0')
  465. $level_where $answer_where
  466. )";
  467. $result = Database::query($sql);
  468. while($row = Database::fetch_array($result, 'ASSOC')) {
  469. $mainQuestionList[] = $row;
  470. }
  471. } else {
  472. // All tests for selected course
  473. // If we have not selected any option in the list-box 'Filter'
  474. $filter = '';
  475. $from = '';
  476. if (isset($courseCategoryId) && $courseCategoryId > 0) {
  477. $from = ", $TBL_COURSE_REL_CATEGORY crc ";
  478. $filter .= " AND
  479. crc.c_id = $selected_course AND
  480. crc.question_id = qu.id AND
  481. crc.category_id = $courseCategoryId";
  482. }
  483. if (isset($exerciseLevel) && $exerciseLevel != -1) {
  484. $filter .= ' AND level='.$exerciseLevel.' ';
  485. }
  486. if (isset($answerType) && $answerType > 0) {
  487. $filter .= ' AND qu.type='.$answerType.' ';
  488. }
  489. if (!empty($session_id) && $session_id != '-1') {
  490. $mainQuestionList = array();
  491. if (!empty($course_list)) {
  492. foreach ($course_list as $course_item) {
  493. $courseItemId = $course_item['real_id'];
  494. if (!empty($selected_course) && $selected_course != '-1') {
  495. if ($selected_course != $courseItemId) {
  496. continue;
  497. }
  498. }
  499. $exerciseList = get_all_exercises($course_item, $session_id);
  500. if (!empty($exerciseList)) {
  501. foreach ($exerciseList as $exercise) {
  502. $my_exercise = new Exercise($courseItemId);
  503. $my_exercise->read($exercise['id']);
  504. if (!empty($my_exercise)) {
  505. if (!empty($my_exercise->questionList)) {
  506. foreach ($my_exercise->questionList as $question_id) {
  507. $question_obj = Question::read(
  508. $question_id,
  509. $courseItemId
  510. );
  511. if ($exerciseLevel != '-1') {
  512. if ($exerciseLevel != $question_obj->level) {
  513. continue;
  514. }
  515. }
  516. if ($answerType > 0) {
  517. if ($answerType != $question_obj->type) {
  518. continue;
  519. }
  520. }
  521. $categoryIdFromQuestion = Testcategory::getCategoryForQuestion(
  522. $question_obj->id,
  523. $selected_course
  524. );
  525. if ($courseCategoryId > 0 &&
  526. $categoryIdFromQuestion != $courseCategoryId
  527. ) {
  528. continue;
  529. }
  530. if (!empty($objExercise) &&
  531. $objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_DIRECT
  532. ) {
  533. if ($question_obj->type == HOT_SPOT_DELINEATION) {
  534. continue;
  535. }
  536. }
  537. $question_row = array(
  538. 'id' => $question_obj->id,
  539. 'question' => $question_obj->question,
  540. 'type' => $question_obj->type,
  541. 'level' => $question_obj->level,
  542. 'exercise_id' => $exercise['id'],
  543. 'exercise_name' => $exercise['title'],
  544. 'course_id' => $courseItemId,
  545. );
  546. $mainQuestionList[] = $question_row;
  547. }
  548. }
  549. }
  550. }
  551. }
  552. }
  553. }
  554. } else {
  555. if ($session_id == -1 or empty($session_id)) {
  556. $session_id = 0;
  557. }
  558. // All tests for the course selected, not in session
  559. $sql = "SELECT DISTINCT qu.id, question, qu.type, level, q.session_id
  560. FROM
  561. $TBL_QUESTIONS as qu,
  562. $TBL_EXERCICE_QUESTION as qt,
  563. $TBL_EXERCICES as q
  564. $from
  565. WHERE
  566. qu.c_id = $selected_course AND
  567. qt.c_id = $selected_course AND
  568. q.c_id = $selected_course AND
  569. qu.id = qt.question_id AND
  570. q.session_id = $session_id AND
  571. q.id = qt.exercice_id $filter
  572. ORDER BY session_id ASC";
  573. $result = Database::query($sql);
  574. while ($row = Database::fetch_array($result, 'ASSOC')) {
  575. $mainQuestionList[] = $row;
  576. }
  577. }
  578. // forces the value to 0
  579. $exerciseId = 0;
  580. }
  581. $nbrQuestions = count($mainQuestionList);
  582. // build the line of the array to display questions
  583. // Actions are different if you launch the question_pool page
  584. // They are different too if you have displayed questions from your course
  585. // Or from another course you are the admin(or session admin)
  586. // from a test or not
  587. /*
  588. +--------------------------------------------+--------------------------------------------+
  589. | NOT IN A TEST | IN A TEST |
  590. +----------------------+---------------------+---------------------+----------------------+
  591. |IN THE COURSE (*) "x | NOT IN THE COURSE o | IN THE COURSE + | NOT IN THE COURSE o |
  592. +----------------------+---------------------+---------------------+----------------------+
  593. |Edit the question | Do nothing | Add question to test|Clone question in test|
  594. |Delete the question | | | |
  595. |(true delete) | | | |
  596. +----------------------+---------------------+---------------------+----------------------+
  597. (*) this is the only way to delete or modify orphan questions
  598. */
  599. //
  600. if ($fromExercise <= 0) {
  601. // NOT IN A TEST - IN THE COURSE
  602. if ($selected_course == api_get_course_int_id()) {
  603. $actionLabel = get_lang('Modify');
  604. $actionIcon1 = "edit";
  605. $actionIcon2 = "delete";
  606. // We are in the course, question title can be a link to the question edit page
  607. $questionTagA = 1;
  608. } else { // NOT IN A TEST - NOT IN THE COURSE
  609. $actionLabel = get_lang('Reuse');
  610. $actionIcon1 = get_lang('MustBeInATest');
  611. $actionIcon2 = "";
  612. // We are not in this course, to messy if we link to the question in another course
  613. $questionTagA = 0;
  614. }
  615. } else {
  616. // IN A TEST - IN THE COURSE
  617. if ($selected_course == api_get_course_int_id()) {
  618. $actionLabel = get_lang('Reuse');
  619. $actionIcon1 = "add";
  620. $actionIcon2 = "";
  621. $questionTagA = 1;
  622. } else {
  623. // IN A TEST - NOT IN THE COURSE
  624. $actionLabel = get_lang('Reuse');
  625. $actionIcon1 = "clone";
  626. $actionIcon2 = "";
  627. $questionTagA = 0;
  628. }
  629. }
  630. // Display table
  631. $header = array(
  632. array(get_lang('QuestionUpperCaseFirstLetter'), false, array("style"=>"text-align:center"), ''),
  633. array(get_lang('Type'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), ''),
  634. array(get_lang('QuestionCategory'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), ''),
  635. array(get_lang('Difficulty'), false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), ''),
  636. array($actionLabel, false, array("style"=>"text-align:center"), array("style"=>"text-align:center"), '')
  637. );
  638. $data = array();
  639. /*$hideDoubles = false;
  640. if (empty($exerciseId) && !empty($session_id) && $session_id != '-1') {
  641. $hideDoubles = true;
  642. }
  643. $questionAdded = array();*/
  644. if (is_array($mainQuestionList)) {
  645. foreach ($mainQuestionList as $question) {
  646. /*if ($hideDoubles) {
  647. if (in_array($question['question'], $questionAdded)) {
  648. continue;
  649. }
  650. }
  651. $questionAdded[$question['question']] = $question;*/
  652. $row = array();
  653. // This function checks if the question can be read
  654. $question_type = get_question_type_for_question(
  655. $selected_course,
  656. $question['id']
  657. );
  658. if (empty($question_type)) {
  659. continue;
  660. }
  661. $sessionId = isset($question['session_id']) ? $question['session_id'] : null;
  662. $exerciseName = isset($question['exercise_name']) ? '<br />('.$question['exercise_id'].') ' : null;
  663. $row[] = get_a_tag_for_question(
  664. $questionTagA,
  665. $fromExercise,
  666. $question['id'],
  667. $question['type'],
  668. $question['question'],
  669. $sessionId
  670. ).$exerciseName;
  671. $row[] = $question_type;
  672. $row[] = get_question_categorie_for_question($selected_course, $question['id']);
  673. $row[] = $question['level'];
  674. $row[] = get_action_icon_for_question(
  675. $actionIcon1,
  676. $fromExercise,
  677. $question['id'],
  678. $question['type'],
  679. $question['question'],
  680. $selected_course,
  681. $courseCategoryId,
  682. $exerciseLevel,
  683. $answerType,
  684. $session_id,
  685. $exerciseId
  686. ).
  687. "&nbsp;".
  688. get_action_icon_for_question(
  689. $actionIcon2,
  690. $fromExercise,
  691. $question['id'],
  692. $question['type'],
  693. $question['question'],
  694. $selected_course,
  695. $courseCategoryId,
  696. $exerciseLevel,
  697. $answerType,
  698. $session_id,
  699. $exerciseId
  700. );
  701. $data[] = $row;
  702. }
  703. }
  704. Display :: display_sortable_table(
  705. $header,
  706. $data,
  707. '',
  708. array('per_page_default' => 999, 'per_page' => 999, 'page_nr' => 1)
  709. );
  710. if (!$nbrQuestions) {
  711. echo get_lang('NoQuestion');
  712. }
  713. Display::display_footer();
  714. /**
  715. * Put the menu entry for level and type to default "Choice"
  716. * It is useful if you change the exercise, you need to reset the other menus
  717. * @author hubert.borderiou 13-10-2011
  718. */
  719. function reset_menu_lvl_type()
  720. {
  721. global $exerciseLevel, $answerType;
  722. $answerType = -1;
  723. $exerciseLevel = -1;
  724. }
  725. /**
  726. * Put the menu entry for exercise and level and type to default "Choice"
  727. * It is useful if you change the course, you need to reset the other menus
  728. * @author hubert.borderiou 13-10-2011
  729. */
  730. function reset_menu_exo_lvl_type()
  731. {
  732. global $exerciseId, $courseCategoryId;
  733. reset_menu_lvl_type();
  734. $exerciseId = 0;
  735. $courseCategoryId = 0;
  736. }
  737. /**
  738. * return the <a> link to admin question, if needed
  739. * @param int $in_addA
  740. * @param int $in_fromex
  741. * @param int $in_questionid
  742. * @param int $in_questiontype
  743. * @param string $in_questionname
  744. * @param int $sessionId
  745. * @return string
  746. * @author hubert.borderiou
  747. */
  748. function get_a_tag_for_question(
  749. $in_addA,
  750. $in_fromex,
  751. $in_questionid,
  752. $in_questiontype,
  753. $in_questionname,
  754. $sessionId
  755. ) {
  756. $res = $in_questionname;
  757. $sessionIcon = null;
  758. if ($in_addA) {
  759. if (!empty($sessionId) && $sessionId != -1) {
  760. $sessionIcon = ' '.Display::return_icon('star.png', get_lang('Session'));
  761. }
  762. $res = "<a href='admin.php?".api_get_cidreq()."&editQuestion=$in_questionid&type=$in_questiontype&fromExercise=$in_fromex'>".
  763. $res.$sessionIcon.
  764. "</a>";
  765. }
  766. return $res;
  767. }
  768. /**
  769. Return the <a> html code for delete, add, clone, edit a question
  770. in_action = the code of the action triggered by the button
  771. from_exercice = the id of the current exercice from which we click on question pool
  772. in_questionid = the id of the current question
  773. in_questiontype = the code of the type of the current question
  774. in_questionname = the name of the question
  775. in_selected_course = the if of the course chosen in the FILTERING MENU
  776. in_courseCategoryId = the id of the category chosen in the FILTERING MENU
  777. in_exerciseLevel = the level of the exercice chosen in the FILTERING MENU
  778. in_answerType = the code of the type of the question chosen in the FILTERING MENU
  779. in_session_id = the id of the session_id chosen in the FILTERING MENU
  780. in_exercice_id = the id of the exercice chosen in the FILTERING MENU
  781. */
  782. function get_action_icon_for_question(
  783. $in_action,
  784. $from_exercice,
  785. $in_questionid,
  786. $in_questiontype,
  787. $in_questionname,
  788. $in_selected_course,
  789. $in_courseCategoryId,
  790. $in_exerciseLevel,
  791. $in_answerType,
  792. $in_session_id,
  793. $in_exercice_id
  794. ) {
  795. $res = "";
  796. $getParams = "&selected_course=$in_selected_course&courseCategoryId=$in_courseCategoryId&exerciseId=$in_exercice_id&exerciseLevel=$in_exerciseLevel&answerType=$in_answerType&session_id=$in_session_id";
  797. switch ($in_action) {
  798. case "delete" :
  799. $res = "<a href='".api_get_self()."?".api_get_cidreq().$getParams."&delete=$in_questionid' onclick='return confirm_your_choice()'>";
  800. $res .= Display::return_icon("delete.png", get_lang('Delete'));
  801. $res .= "</a>";
  802. break;
  803. case "edit" :
  804. $res = get_a_tag_for_question(
  805. 1,
  806. $from_exercice,
  807. $in_questionid,
  808. $in_questiontype,
  809. Display::return_icon("edit.png", get_lang('Modify')),
  810. $in_session_id
  811. );
  812. break;
  813. case "add":
  814. // add if question is not already in test
  815. $myObjEx = new Exercise();
  816. $myObjEx->read($from_exercice);
  817. if (!$myObjEx->isInList($in_questionid)) {
  818. $res = "<a href='".api_get_self()."?".api_get_cidreq().$getParams."&recup=$in_questionid&fromExercise=$from_exercice'>";
  819. $res .= Display::return_icon("view_more_stats.gif", get_lang('InsertALinkToThisQuestionInTheExercise'));
  820. $res .= "</a>";
  821. } else {
  822. $res = "-";
  823. }
  824. unset($myObjEx);
  825. break;
  826. case "clone":
  827. $url = api_get_self()."?".api_get_cidreq().$getParams."&amp;copy_question=$in_questionid&amp;course_id=$in_selected_course&amp;fromExercise=$from_exercice";
  828. $res = Display::url(
  829. Display::return_icon('cd.gif', get_lang('ReUseACopyInCurrentTest')),
  830. $url
  831. );
  832. break;
  833. default :
  834. $res = $in_action;
  835. break;
  836. }
  837. return $res;
  838. }
  839. /**
  840. * Return the icon for the question type
  841. * @author hubert.borderiou 13-10-2011
  842. */
  843. function get_question_type_for_question($in_selectedcourse, $in_questionid)
  844. {
  845. $myObjQuestion = Question::read($in_questionid, $in_selectedcourse);
  846. $questionType = null;
  847. if (!empty($myObjQuestion)) {
  848. list($typeImg, $typeExpl) = $myObjQuestion->get_type_icon_html();
  849. $questionType = Display::tag('div', Display::return_icon($typeImg, $typeExpl, array(), 32), array());
  850. unset($myObjQuestion);
  851. }
  852. return $questionType;
  853. }
  854. /**
  855. * Return the name of the category for the question in a course
  856. * @author hubert.borderiou 13-10-2011
  857. */
  858. function get_question_categorie_for_question($in_courseid, $in_questionid)
  859. {
  860. $cat = Testcategory::getCategoryNameForQuestion($in_questionid, $in_courseid);
  861. return $cat;
  862. }