TestCategory.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class TestCategory
  5. * @author hubert.borderiou
  6. * @author Julio Montoya - several fixes
  7. * @todo rename to ExerciseCategory
  8. */
  9. class TestCategory
  10. {
  11. public $id;
  12. public $name;
  13. public $description;
  14. /**
  15. * Constructor of the class Category
  16. * If you give an in_id and no in_name, you get info concerning the category of id=in_id
  17. * otherwise, you've got an category objet avec your in_id, in_name, in_descr
  18. *
  19. * @param int $id
  20. * @param string $name
  21. * @param string $description
  22. *
  23. * @author - Hubert Borderiou
  24. */
  25. public function __construct($id = 0, $name = '', $description = "")
  26. {
  27. if ($id != 0 && $name == "") {
  28. $obj = new TestCategory();
  29. $obj->getCategory($id);
  30. $this->id = $obj->id;
  31. $this->name = $obj->name;
  32. $this->description = $obj->description;
  33. } else {
  34. $this->id = $id;
  35. $this->name = $name;
  36. $this->description = $description;
  37. }
  38. }
  39. /**
  40. * return the TestCategory object with id=in_id
  41. * @param int $id
  42. *
  43. * @return TestCategory
  44. */
  45. public function getCategory($id)
  46. {
  47. $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  48. $id = intval($id);
  49. $sql = "SELECT * FROM $table
  50. WHERE id = $id AND c_id=".api_get_course_int_id();
  51. $res = Database::query($sql);
  52. if (Database::num_rows($res)) {
  53. $row = Database::fetch_array($res);
  54. $this->id = $row['id'];
  55. $this->name = $row['title'];
  56. $this->description = $row['description'];
  57. }
  58. }
  59. /**
  60. * add TestCategory in the database if name doesn't already exists
  61. */
  62. public function addCategoryInBDD()
  63. {
  64. $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  65. $v_name = $this->name;
  66. $v_name = Database::escape_string($v_name);
  67. $v_description = $this->description;
  68. $v_description = Database::escape_string($v_description);
  69. // check if name already exists
  70. $sql = "SELECT count(*) AS nb FROM $table
  71. WHERE title = '$v_name' AND c_id=".api_get_course_int_id();
  72. $result_verif = Database::query($sql);
  73. $data_verif = Database::fetch_array($result_verif);
  74. // lets add in BDD if not the same name
  75. if ($data_verif['nb'] <= 0) {
  76. $c_id = api_get_course_int_id();
  77. $params = [
  78. 'c_id' => $c_id,
  79. 'title' => $v_name,
  80. 'description' => $v_description,
  81. ];
  82. $new_id = Database::insert($table, $params);
  83. if ($new_id) {
  84. $sql = "UPDATE $table SET id = iid WHERE iid = $new_id";
  85. Database::query($sql);
  86. // add test_category in item_property table
  87. $course_id = api_get_course_int_id();
  88. $course_info = api_get_course_info_by_id($course_id);
  89. api_item_property_update(
  90. $course_info,
  91. TOOL_TEST_CATEGORY,
  92. $new_id,
  93. 'TestCategoryAdded',
  94. api_get_user_id()
  95. );
  96. }
  97. return $new_id;
  98. } else {
  99. return false;
  100. }
  101. }
  102. /**
  103. * Removes the category from the database
  104. * if there were question in this category, the link between question and category is removed
  105. */
  106. public function removeCategory()
  107. {
  108. $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  109. $tbl_question_rel_cat = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  110. $v_id = intval($this->id);
  111. $course_id = api_get_course_int_id();
  112. $sql = "DELETE FROM $table
  113. WHERE id= $v_id AND c_id=".$course_id;
  114. $result = Database::query($sql);
  115. if (Database::affected_rows($result) <= 0) {
  116. return false;
  117. } else {
  118. // remove link between question and category
  119. $sql2 = "DELETE FROM $tbl_question_rel_cat
  120. WHERE category_id = $v_id AND c_id=".$course_id;
  121. Database::query($sql2);
  122. // item_property update
  123. $course_info = api_get_course_info_by_id($course_id);
  124. api_item_property_update(
  125. $course_info,
  126. TOOL_TEST_CATEGORY,
  127. $this->id,
  128. 'TestCategoryDeleted',
  129. api_get_user_id()
  130. );
  131. return true;
  132. }
  133. }
  134. /**
  135. * Modify category name or description of category with id=in_id
  136. */
  137. public function modifyCategory()
  138. {
  139. $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  140. $v_id = intval($this->id);
  141. $v_name = Database::escape_string($this->name);
  142. $v_description = Database::escape_string($this->description);
  143. $sql = "UPDATE $table SET
  144. title = '$v_name',
  145. description = '$v_description'
  146. WHERE id = $v_id AND c_id=".api_get_course_int_id();
  147. $result = Database::query($sql);
  148. if (Database::affected_rows($result) <= 0) {
  149. return false;
  150. } else {
  151. // item_property update
  152. $course_id = api_get_course_int_id();
  153. $course_info = api_get_course_info_by_id($course_id);
  154. api_item_property_update(
  155. $course_info,
  156. TOOL_TEST_CATEGORY,
  157. $this->id,
  158. 'TestCategoryModified',
  159. api_get_user_id()
  160. );
  161. return true;
  162. }
  163. }
  164. /**
  165. * Gets the number of question of category id=in_id
  166. */
  167. public function getCategoryQuestionsNumber()
  168. {
  169. $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  170. $in_id = intval($this->id);
  171. $sql = "SELECT count(*) AS nb
  172. FROM $table
  173. WHERE category_id=$in_id AND c_id=".api_get_course_int_id();
  174. $res = Database::query($sql);
  175. $row = Database::fetch_array($res);
  176. return $row['nb'];
  177. }
  178. /**
  179. * @param string $in_color
  180. */
  181. public function display($in_color="#E0EBF5")
  182. {
  183. echo "<textarea style='background-color:$in_color; width:60%; height:100px;'>";
  184. print_r($this);
  185. echo "</textarea>";
  186. }
  187. /**
  188. * Return an array of all Category objects in the database
  189. * If in_field=="" Return an array of all category objects in the database
  190. * Otherwise, return an array of all in_field value
  191. * in the database (in_field = id or name or description)
  192. */
  193. public static function getCategoryListInfo($in_field = "", $courseId = "")
  194. {
  195. if (empty($courseId) || $courseId=="") {
  196. $courseId = api_get_course_int_id();
  197. }
  198. $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  199. $in_field = Database::escape_string($in_field);
  200. $tabres = array();
  201. if ($in_field == "") {
  202. $sql = "SELECT * FROM $table
  203. WHERE c_id=$courseId ORDER BY title ASC";
  204. $res = Database::query($sql);
  205. while ($row = Database::fetch_array($res)) {
  206. $tmpcat = new TestCategory(
  207. $row['id'],
  208. $row['title'],
  209. $row['description']
  210. );
  211. $tabres[] = $tmpcat;
  212. }
  213. } else {
  214. $sql = "SELECT $in_field FROM $table
  215. WHERE c_id = $courseId
  216. ORDER BY $in_field ASC";
  217. $res = Database::query($sql);
  218. while ($row = Database::fetch_array($res)) {
  219. $tabres[] = $row[$in_field];
  220. }
  221. }
  222. return $tabres;
  223. }
  224. /**
  225. * Return the TestCategory id for question with question_id = $questionId
  226. * In this version, a question has only 1 TestCategory.
  227. * Return the TestCategory id, 0 if none
  228. * @param int $questionId
  229. * @param int $courseId
  230. *
  231. * @return int
  232. */
  233. public static function getCategoryForQuestion($questionId, $courseId ="")
  234. {
  235. $result = 0;
  236. if (empty($courseId) || $courseId == "") {
  237. $courseId = api_get_course_int_id();
  238. }
  239. $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  240. $questionId = intval($questionId);
  241. $sql = "SELECT category_id
  242. FROM $table
  243. WHERE question_id = $questionId AND c_id = $courseId";
  244. $res = Database::query($sql);
  245. if (Database::num_rows($res) > 0) {
  246. $data = Database::fetch_array($res);
  247. $result = $data['category_id'];
  248. }
  249. return $result;
  250. }
  251. /**
  252. * true if question id has a category
  253. */
  254. public static function isQuestionHasCategory($questionId)
  255. {
  256. if (TestCategory::getCategoryForQuestion($questionId) > 0) {
  257. return true;
  258. }
  259. return false;
  260. }
  261. /**
  262. Return the category name for question with question_id = $questionId
  263. In this version, a question has only 1 category.
  264. Return the category id, "" if none
  265. */
  266. public static function getCategoryNameForQuestion(
  267. $questionId,
  268. $courseId = ""
  269. ) {
  270. if (empty($courseId) || $courseId=="") {
  271. $courseId = api_get_course_int_id();
  272. }
  273. $catid = TestCategory::getCategoryForQuestion($questionId, $courseId);
  274. $result = ""; // result
  275. $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  276. $catid = intval($catid);
  277. $sql = "SELECT title FROM $table
  278. WHERE id = $catid AND c_id = $courseId";
  279. $res = Database::query($sql);
  280. $data = Database::fetch_array($res);
  281. if (Database::num_rows($res) > 0) {
  282. $result = $data['title'];
  283. }
  284. return $result;
  285. }
  286. /**
  287. * Return the list of differents categories ID for a test in the current course
  288. * input : test_id
  289. * return : array of category id (integer)
  290. * hubert.borderiou 07-04-2011
  291. */
  292. public static function getListOfCategoriesIDForTest($in_testid)
  293. {
  294. // parcourir les questions d'un test, recup les categories uniques dans un tableau
  295. $result = array();
  296. $quiz = new Exercise();
  297. $quiz->read($in_testid);
  298. $tabQuestionList = $quiz->selectQuestionList();
  299. // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ???
  300. for ($i=1; $i <= count($tabQuestionList); $i++) {
  301. if (!in_array(TestCategory::getCategoryForQuestion($tabQuestionList[$i]), $result)) {
  302. $result[] = TestCategory::getCategoryForQuestion($tabQuestionList[$i]);
  303. }
  304. }
  305. return $result;
  306. }
  307. /**
  308. * return the list of different categories NAME for a test
  309. * input : test_id
  310. * return : array of string
  311. * hubert.borderiou 07-04-2011
  312. * @author function rewrote by jmontoya
  313. */
  314. public static function getListOfCategoriesNameForTest($in_testid)
  315. {
  316. $tabcatName = array();
  317. $tabcatID = self::getListOfCategoriesIDForTest($in_testid);
  318. for ($i=0; $i < count($tabcatID); $i++) {
  319. $cat = new TestCategory($tabcatID[$i]);
  320. $tabcatName[$cat->id] = $cat->name;
  321. }
  322. return $tabcatName;
  323. }
  324. /**
  325. * return the number of differents categories for a test
  326. * input : test_id
  327. * return : integer
  328. * hubert.borderiou 07-04-2011
  329. */
  330. public static function getNumberOfCategoriesForTest($in_testid)
  331. {
  332. return count(TestCategory::getListOfCategoriesIDForTest($in_testid));
  333. }
  334. /**
  335. * return the number of question of a category id in a test
  336. * @param int $exerciseId
  337. * @param int $categoryId
  338. *
  339. * @return integer
  340. *
  341. * @author hubert.borderiou 07-04-2011
  342. */
  343. public static function getNumberOfQuestionsInCategoryForTest($exerciseId, $categoryId)
  344. {
  345. $nbCatResult = 0;
  346. $quiz = new Exercise();
  347. $quiz->read($exerciseId);
  348. $tabQuestionList = $quiz->selectQuestionList();
  349. // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ? ? ?
  350. for ($i=1; $i <= count($tabQuestionList); $i++) {
  351. if (TestCategory::getCategoryForQuestion($tabQuestionList[$i]) == $categoryId) {
  352. $nbCatResult++;
  353. }
  354. }
  355. return $nbCatResult;
  356. }
  357. /**
  358. * return the number of question for a test using random by category
  359. * input : test_id, number of random question (min 1)
  360. * hubert.borderiou 07-04-2011
  361. * question without categories are not counted
  362. */
  363. public static function getNumberOfQuestionRandomByCategory($exerciseId, $in_nbrandom)
  364. {
  365. $nbquestionresult = 0;
  366. $tabcatid = TestCategory::getListOfCategoriesIDForTest($exerciseId);
  367. for ($i=0; $i < count($tabcatid); $i++) {
  368. if ($tabcatid[$i] > 0) { // 0 = no category for this questio
  369. $nbQuestionInThisCat = TestCategory::getNumberOfQuestionsInCategoryForTest($exerciseId, $tabcatid[$i]);
  370. if ($nbQuestionInThisCat > $in_nbrandom) {
  371. $nbquestionresult += $in_nbrandom;
  372. }
  373. else {
  374. $nbquestionresult += $nbQuestionInThisCat;
  375. }
  376. }
  377. }
  378. return $nbquestionresult;
  379. }
  380. /**
  381. * Return an array (id=>name)
  382. * tabresult[0] = get_lang('NoCategory');
  383. *
  384. * @param int $courseId
  385. *
  386. * @return array
  387. *
  388. */
  389. public static function getCategoriesIdAndName($courseId = "")
  390. {
  391. if (empty($courseId)) {
  392. $courseId = api_get_course_int_id();
  393. }
  394. $tabcatobject = TestCategory::getCategoryListInfo("", $courseId);
  395. $tabresult = array("0"=>get_lang('NoCategorySelected'));
  396. for ($i=0; $i < count($tabcatobject); $i++) {
  397. $tabresult[$tabcatobject[$i]->id] = $tabcatobject[$i]->name;
  398. }
  399. return $tabresult;
  400. }
  401. /**
  402. * return an array of question_id for each category
  403. * tabres[0] = array of question id with category id = 0 (i.e. no category)
  404. * tabres[24] = array of question id with category id = 24
  405. * In this version, a question has 0 or 1 category
  406. *
  407. * @param int $exerciseId
  408. * @return array
  409. */
  410. public static function getQuestionsByCat($exerciseId)
  411. {
  412. $em = Database::getManager();
  413. $qb = $em->createQueryBuilder();
  414. $res = $qb
  415. ->select('qrc.questionId', 'qrc.categoryId')
  416. ->from('ChamiloCourseBundle:CQuizQuestionRelCategory', 'qrc')
  417. ->innerJoin(
  418. 'ChamiloCourseBundle:CQuizRelQuestion',
  419. 'eq',
  420. Doctrine\ORM\Query\Expr\Join::WITH,
  421. 'qrc.questionId = eq.questionId AND qrc.cId = eq.cId'
  422. )
  423. ->where(
  424. $qb->expr()->eq('eq.exerciceId', $exerciseId)
  425. )
  426. ->andWhere(
  427. $qb->expr()->eq('eq.cId', api_get_course_int_id())
  428. )
  429. ->getQuery()
  430. ->getResult();
  431. $list = array();
  432. foreach ($res as $data) {
  433. if (!isset($list[$data['categoryId']])) {
  434. $list[$data['categoryId']] = array();
  435. }
  436. $list[$data['categoryId']][] = $data['questionId'];
  437. }
  438. return $list;
  439. }
  440. /**
  441. * return a tab of $in_number random elements of $in_tab
  442. */
  443. public static function getNElementsFromArray($in_tab, $in_number)
  444. {
  445. $tabres = $in_tab;
  446. shuffle($tabres);
  447. if ($in_number < count($tabres)) {
  448. $tabres = array_slice($tabres, 0, $in_number);
  449. }
  450. return $tabres;
  451. }
  452. /**
  453. * display the category
  454. */
  455. public static function displayCategoryAndTitle($questionId, $in_display_category_name = 1)
  456. {
  457. echo self::returnCategoryAndTitle($questionId, $in_display_category_name);
  458. }
  459. /**
  460. * @param int $questionId
  461. * @param int $in_display_category_name
  462. * @return null|string
  463. */
  464. public static function returnCategoryAndTitle($questionId, $in_display_category_name = 1)
  465. {
  466. $is_student = !(api_is_allowed_to_edit(null,true) || api_is_session_admin());
  467. // @todo fix $_SESSION['objExercise']
  468. $objExercise = isset($_SESSION['objExercise']) ? $_SESSION['objExercise'] : null;
  469. if (!empty($objExercise)) {
  470. $in_display_category_name = $objExercise->display_category_name;
  471. }
  472. $content = null;
  473. if (TestCategory::getCategoryNameForQuestion($questionId) != "" && ($in_display_category_name == 1 || !$is_student)) {
  474. $content .= '<div class="page-header">';
  475. $content .= '<h4>'.get_lang('Category').": ".TestCategory::getCategoryNameForQuestion($questionId).'</h4>';
  476. $content .= "</div>";
  477. }
  478. return $content;
  479. }
  480. /**
  481. * Display signs [+] and/or (>0) after question title if question has options
  482. * scoreAlwaysPositive and/or uncheckedMayScore
  483. */
  484. public function displayQuestionOption($in_objQuestion)
  485. {
  486. if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->scoreAlwaysPositive) {
  487. echo "<span style='font-size:75%'> (>0)</span>";
  488. }
  489. if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->uncheckedMayScore) {
  490. echo "<span style='font-size:75%'> [+]</span>";
  491. }
  492. }
  493. /**
  494. * sortTabByBracketLabel ($tabCategoryQuestions)
  495. * key of $tabCategoryQuestions are the category id (0 for not in a category)
  496. * value is the array of question id of this category
  497. * Sort question by Category
  498. */
  499. public static function sortTabByBracketLabel($in_tab)
  500. {
  501. $tabResult = array();
  502. $tabCatName = array(); // tab of category name
  503. while (list($cat_id, $tabquestion) = each($in_tab)) {
  504. $catTitle = new TestCategory($cat_id);
  505. $tabCatName[$cat_id] = $catTitle->name;
  506. }
  507. reset($in_tab);
  508. // sort table by value, keeping keys as they are
  509. asort($tabCatName);
  510. // keys of $tabCatName are keys order for $in_tab
  511. while (list($key, $val) = each($tabCatName)) {
  512. $tabResult[$key] = $in_tab[$key];
  513. }
  514. return $tabResult;
  515. }
  516. /**
  517. * return the number max of question in a category
  518. * count the number of questions in all categories, and return the max
  519. * @param int $exerciseId
  520. * @author - hubert borderiou
  521. */
  522. public static function getNumberMaxQuestionByCat($exerciseId)
  523. {
  524. $res_num_max = 0;
  525. // foreach question
  526. $tabcatid = TestCategory::getListOfCategoriesIDForTest($exerciseId);
  527. for ($i=0; $i < count($tabcatid); $i++) {
  528. if ($tabcatid[$i] > 0) { // 0 = no category for this question
  529. $nbQuestionInThisCat = TestCategory::getNumberOfQuestionsInCategoryForTest($exerciseId, $tabcatid[$i]);
  530. if ($nbQuestionInThisCat > $res_num_max) {
  531. $res_num_max = $nbQuestionInThisCat;
  532. }
  533. }
  534. }
  535. return $res_num_max;
  536. }
  537. /**
  538. * Returns a category summary report
  539. * @params int exercise id
  540. * @params array pre filled array with the category_id, score, and weight
  541. * example: array(1 => array('score' => '10', 'total' => 20));
  542. */
  543. public static function get_stats_table_by_attempt($exercise_id, $category_list = array())
  544. {
  545. if (empty($category_list)) {
  546. return null;
  547. }
  548. $category_name_list = TestCategory::getListOfCategoriesNameForTest($exercise_id);
  549. $table = new HTML_Table(array('class' => 'data_table'));
  550. $table->setHeaderContents(0, 0, get_lang('Categories'));
  551. $table->setHeaderContents(0, 1, get_lang('AbsoluteScore'));
  552. $table->setHeaderContents(0, 2, get_lang('RelativeScore'));
  553. $row = 1;
  554. $none_category = array();
  555. if (isset($category_list['none'])) {
  556. $none_category = $category_list['none'];
  557. unset($category_list['none']);
  558. }
  559. $total = array();
  560. if (isset($category_list['total'])) {
  561. $total = $category_list['total'];
  562. unset($category_list['total']);
  563. }
  564. if (count($category_list) > 1) {
  565. foreach ($category_list as $category_id => $category_item) {
  566. $table->setCellContents($row, 0, $category_name_list[$category_id]);
  567. $table->setCellContents($row, 1, ExerciseLib::show_score($category_item['score'], $category_item['total'], false));
  568. $table->setCellContents($row, 2, ExerciseLib::show_score($category_item['score'], $category_item['total'], true, false, true));
  569. $row++;
  570. }
  571. if (!empty($none_category)) {
  572. $table->setCellContents($row, 0, get_lang('None'));
  573. $table->setCellContents($row, 1, ExerciseLib::show_score($none_category['score'], $none_category['total'], false));
  574. $table->setCellContents($row, 2, ExerciseLib::show_score($none_category['score'], $none_category['total'], true, false, true));
  575. $row++;
  576. }
  577. if (!empty($total)) {
  578. $table->setCellContents($row, 0, get_lang('Total'));
  579. $table->setCellContents($row, 1, ExerciseLib::show_score($total['score'], $total['total'], false));
  580. $table->setCellContents($row, 2, ExerciseLib::show_score($total['score'], $total['total'], true, false, true));
  581. }
  582. return $table->toHtml();
  583. }
  584. return null;
  585. }
  586. /**
  587. * Return true if a category already exists with the same name
  588. * @param string $in_name
  589. *
  590. * @return bool
  591. */
  592. public static function category_exists_with_title($in_name)
  593. {
  594. $tab_test_category = TestCategory::getCategoryListInfo("title");
  595. foreach ($tab_test_category as $title) {
  596. if ($title == $in_name) {
  597. return true;
  598. }
  599. }
  600. return false;
  601. }
  602. /**
  603. * Return the id of the test category with title = $in_title
  604. * @param $in_title
  605. * @param int $in_c_id
  606. *
  607. * @return int is id of test category
  608. */
  609. public static function get_category_id_for_title($title, $courseId = 0)
  610. {
  611. $out_res = 0;
  612. if (empty($courseId)) {
  613. $courseId = api_get_course_int_id();
  614. }
  615. $courseId = intval($courseId);
  616. $tbl_cat = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  617. $sql = "SELECT id FROM $tbl_cat
  618. WHERE c_id = $courseId AND title = '".Database::escape_string($title)."'";
  619. $res = Database::query($sql);
  620. if (Database::num_rows($res) > 0) {
  621. $data = Database::fetch_array($res);
  622. $out_res = $data['id'];
  623. }
  624. return $out_res;
  625. }
  626. /**
  627. * Add a relation between question and category in table c_quiz_question_rel_category
  628. * @param int $categoryId
  629. * @param int $questionId
  630. * @param int $courseId
  631. *
  632. * @return int
  633. */
  634. public static function add_category_for_question_id($categoryId, $questionId, $courseId)
  635. {
  636. $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  637. // if question doesn't have a category
  638. // @todo change for 1.10 when a question can have several categories
  639. if (TestCategory::getCategoryForQuestion($questionId, $courseId) == 0 &&
  640. $questionId > 0 &&
  641. $courseId > 0
  642. ) {
  643. $sql = "INSERT INTO $table (c_id, question_id, category_id)
  644. VALUES (".intval($courseId).", ".intval($questionId).", ".intval($categoryId).")";
  645. Database::query($sql);
  646. $id = Database::insert_id();
  647. return $id;
  648. }
  649. return false;
  650. }
  651. /**
  652. * @param int $courseId
  653. * @param int $sessionId
  654. *
  655. * @return array
  656. */
  657. public function getCategories($courseId, $sessionId = 0)
  658. {
  659. $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  660. $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
  661. $sessionId = intval($sessionId);
  662. $courseId = intval($courseId);
  663. if (empty($sessionId)) {
  664. $sessionCondition = api_get_session_condition($sessionId, true, false, 'i.session_id');
  665. } else {
  666. $sessionCondition = api_get_session_condition($sessionId, true, true, 'i.session_id');
  667. }
  668. if (empty($courseId)) {
  669. return array();
  670. }
  671. $sql = "SELECT c.* FROM $table c
  672. INNER JOIN $itemProperty i
  673. ON c.c_id = i.c_id AND i.ref = c.id
  674. WHERE
  675. c.c_id = $courseId AND
  676. i.tool = '".TOOL_TEST_CATEGORY."'
  677. $sessionCondition
  678. ORDER BY title";
  679. $result = Database::query($sql);
  680. return Database::store_result($result, 'ASSOC');
  681. }
  682. /**
  683. * @param int $courseId
  684. * @param int $sessionId
  685. * @return string
  686. */
  687. public function displayCategories($courseId, $sessionId = 0)
  688. {
  689. $categories = $this->getCategories($courseId, $sessionId);
  690. $html = '';
  691. foreach ($categories as $category) {
  692. $tmpobj = new TestCategory($category['id']);
  693. $nb_question = $tmpobj->getCategoryQuestionsNumber();
  694. $rowname = self::protectJSDialogQuote($category['title']);
  695. $nb_question_label = $nb_question == 1 ? $nb_question . ' ' . get_lang('Question') : $nb_question . ' ' . get_lang('Questions');
  696. //$html .= '<div class="sectiontitle" id="id_cat' . $category['id'] . '">';
  697. $content = "<span style='float:right'>" . $nb_question_label . "</span>";
  698. $content .= '<div class="sectioncomment">';
  699. $content .= $category['description'];
  700. $content .= '</div>';
  701. $links = '<a href="' . api_get_self() . '?action=editcategory&category_id=' . $category['id'] . '">' .
  702. Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>';
  703. $links .= ' <a href="' . api_get_self() . '?action=deletecategory&category_id=' . $category['id'] . '" ';
  704. $links .= 'onclick="return confirmDelete(\'' . self::protectJSDialogQuote(get_lang('DeleteCategoryAreYouSure') . '[' . $rowname) . '] ?\', \'id_cat' . $category['id'] . '\');">';
  705. $links .= Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
  706. $html .= Display::panel($content, $category['title'].$links);
  707. }
  708. return $html;
  709. }
  710. // To allowed " in javascript dialog box without bad surprises
  711. // replace " with two '
  712. public function protectJSDialogQuote($in_txt)
  713. {
  714. $res = $in_txt;
  715. $res = str_replace("'", "\'", $res);
  716. $res = str_replace('"', "\'\'", $res); // super astuce pour afficher les " dans les boite de dialogue
  717. return $res;
  718. }
  719. }