testcategory.class.php 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * @author hubert.borderiou & jmontoya
  5. */
  6. class Testcategory
  7. {
  8. public $id;
  9. public $name; //why using name?? Use title as in the db!
  10. public $title;
  11. public $description;
  12. public $parent_id;
  13. public $parent_path;
  14. public $category_array_tree;
  15. public $type;
  16. public $course_id;
  17. public $c_id; // from db
  18. public $root;
  19. public $visibility;
  20. /**
  21. * Constructor of the class Category
  22. * @author - Hubert Borderiou
  23. * If you give an in_id and no in_name, you get info concerning the category of id=in_id
  24. * otherwise, you've got an category objet avec your in_id, in_name, in_descr
  25. * @todo fix this function
  26. *
  27. * @param int $in_id
  28. * @param string $in_name
  29. * @param string $in_description
  30. * @param int $parent_id
  31. * @param string $type possible values: all, simple, global
  32. * @param int $course_id
  33. * @param int visibility
  34. */
  35. public function Testcategory($in_id = 0, $in_name = '', $in_description = "", $parent_id = 0, $type = 'simple', $course_id = null, $visibility = 1)
  36. {
  37. if ($in_id != 0 && $in_name == "") {
  38. $tmpobj = new Testcategory(0, '', '', 0, 'simple', $course_id);
  39. $tmpobj->getCategory($in_id);
  40. $this->id = $tmpobj->id;
  41. $this->name = $tmpobj->name;
  42. $this->title = $tmpobj->name;
  43. $this->description = $tmpobj->description;
  44. $this->parent_id = $tmpobj->parent_id;
  45. $this->parent_path = $this->name;
  46. $this->c_id = isset($course_id) ? $course_id : $tmpobj->c_id;
  47. $this->root = $tmpobj->root;
  48. $this->visibility = $tmpobj->visibility;
  49. if (!empty($tmpobj->parent_id)) {
  50. // Default values and the course_id passed.
  51. $category = new Testcategory($tmpobj->parent_id, '', '', 0, 'simple', $course_id);
  52. $this->parent_path = $category->parent_path.' > '.$this->name;
  53. }
  54. } else {
  55. $this->id = $in_id;
  56. $this->name = $in_name;
  57. $this->description = $in_description;
  58. $this->parent_id = $parent_id;
  59. $this->visibility = $visibility;
  60. }
  61. $this->type = $type;
  62. if (!empty($course_id)) {
  63. $this->course_id = $course_id;
  64. } else {
  65. $this->course_id = api_get_course_int_id();
  66. }
  67. }
  68. /**
  69. * Return the Testcategory object with id=in_id
  70. * @param int $id
  71. * @return bool
  72. * @assert () === false
  73. */
  74. public function getCategory($id)
  75. {
  76. if (empty($id)) {
  77. return false;
  78. }
  79. $t_cattable = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  80. $id = intval($id);
  81. $sql = "SELECT * FROM $t_cattable WHERE iid = $id ";
  82. $res = Database::query($sql);
  83. $numRows = Database::num_rows($res);
  84. if ($numRows > 0) {
  85. $row = Database::fetch_array($res);
  86. $this->id = $row['iid'];
  87. $this->title = $this->name = $row['title'];
  88. $this->description = $row['description'];
  89. $this->parent_id = $row['parent_id'];
  90. $this->c_id = $row['c_id'];
  91. $this->root = $row['root'];
  92. $this->visibility = $row['visibility'];
  93. } else {
  94. return false;
  95. }
  96. }
  97. /**
  98. * Add Testcategory in the database if name doesn't already exists
  99. *
  100. */
  101. public function addCategoryInBDD()
  102. {
  103. $t_cattable = Database :: get_course_table(TABLE_QUIZ_CATEGORY);
  104. $v_name = Database::escape_string($this->name);
  105. $parent_id = intval($this->parent_id);
  106. $course_id = $this->course_id;
  107. $courseCondition = " AND c_id = $course_id ";
  108. if ($this->type == 'global') {
  109. $course_id = '';
  110. $courseCondition = null;
  111. }
  112. // Only admins can add global categories
  113. if ($this->type == 'global' && empty($course_id) && (!api_is_platform_admin() && !api_is_question_manager())) {
  114. return false;
  115. }
  116. // Check if name already exists.
  117. $sql = "SELECT count(*) AS nb FROM $t_cattable WHERE title = '$v_name' $courseCondition";
  118. $result = Database::query($sql);
  119. $data = Database::fetch_array($result);
  120. // lets add in BD if not the same name
  121. if ($data['nb'] <= 0) {
  122. // @todo inject the app in the class
  123. global $app;
  124. $category = new \Entity\CQuizCategory();
  125. $category->setTitle($this->name);
  126. $category->setDescription($this->description);
  127. if (!empty($parent_id)) {
  128. $parent = $app['orm.ems']['db_write']->find('\Entity\CQuizCategory', $parent_id);
  129. if ($parent) {
  130. $category->setParent($parent);
  131. }
  132. }
  133. $category->setCId($course_id);
  134. $app['orm.ems']['db_write']->persist($category);
  135. $app['orm.ems']['db_write']->flush();
  136. if ($category->getIid()) {
  137. return $category->getIid();
  138. } else {
  139. return false;
  140. }
  141. } else {
  142. return false;
  143. }
  144. }
  145. /**
  146. * Modify category name or description of category with id=in_id
  147. */
  148. public function modifyCategory()
  149. {
  150. // @todo inject the app in the class
  151. global $app;
  152. $category = $app['orm.ems']['db_write']->find('\Entity\CQuizCategory', $this->id);
  153. if (!$category) {
  154. return false;
  155. }
  156. $courseId = $category->getCId();
  157. //Only admins can delete global categories
  158. if (empty($courseId) && !api_is_platform_admin()) {
  159. return false;
  160. }
  161. $category->setTitle($this->name);
  162. $category->setDescription($this->description);
  163. $category->setVisibility($this->visibility);
  164. if (!empty($this->parent_id)) {
  165. foreach ($this->parent_id as $parentId) {
  166. if ($this->id == $parentId) {
  167. continue;
  168. }
  169. $parent = $app['orm.ems']['db_write']->find('\Entity\CQuizCategory', $parentId);
  170. if ($parent) {
  171. $category->setParent($parent);
  172. }
  173. break;
  174. }
  175. } else {
  176. $category->setParent(null);
  177. }
  178. $app['orm.ems']['db_write']->persist($category);
  179. $app['orm.ems']['db_write']->flush();
  180. if ($category->getIid()) {
  181. return $category->getIid();
  182. } else {
  183. return false;
  184. }
  185. }
  186. /**
  187. * Removes the category with id=in_id from the database if no question use this category
  188. * @todo I'm removing the $in_id parameter because it seems that you're using $this->id instead of $in_id after confirmation delete this
  189. * jmontoya
  190. */
  191. public function removeCategory()
  192. {
  193. global $app;
  194. $category = $app['orm.ems']['db_write']->find('\Entity\CQuizCategory', $this->id);
  195. if (!$category) {
  196. return false;
  197. }
  198. //Only admins can delete global categories
  199. $courseId = $category->getCId();
  200. //Only admins can delete global categories
  201. if (empty($courseId) && !api_is_platform_admin() || api_is_question_manager()) {
  202. return false;
  203. }
  204. $repo = $app['orm.ems']['db_write']->getRepository('Entity\CQuizCategory');
  205. $repo->removeFromTree($category);
  206. // clear cached nodes
  207. $app['orm.ems']['db_write']->clear();
  208. return true;
  209. }
  210. /**
  211. * @param string $title
  212. * @param int $course_id
  213. * @return bool
  214. */
  215. public function get_category_by_title($title , $course_id = 0)
  216. {
  217. $table = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  218. $course_id = intval($course_id);
  219. $title = Database::escape_string($title);
  220. $sql = "SELECT * FROM $table WHERE title = '$title' AND c_id IN ('0', '$course_id')LIMIT 1";
  221. $result = Database::query($sql);
  222. if (Database::num_rows($result)) {
  223. $result = Database::store_result($result, 'ASSOC');
  224. return $result[0];
  225. }
  226. return false;
  227. }
  228. /**
  229. *
  230. * Get categories by title for json calls
  231. * @param string $tag
  232. * @return array
  233. * @assert() === false
  234. */
  235. public function get_categories_by_keyword($tag)
  236. {
  237. if (empty($tag)) {
  238. return false;
  239. }
  240. $table = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  241. $sql = "SELECT iid, title, c_id FROM $table WHERE 1=1 ";
  242. $tag = Database::escape_string($tag);
  243. $where_condition = array();
  244. if (!empty($tag)) {
  245. $condition = ' LIKE "%'.$tag.'%"';
  246. $where_condition = array(
  247. "title $condition",
  248. );
  249. $where_condition = ' AND ('.implode(' OR ', $where_condition).') ';
  250. }
  251. switch ($this->type) {
  252. case 'simple':
  253. $course_condition = " AND c_id = '".api_get_course_int_id()."' ";
  254. break;
  255. case 'global':
  256. $course_condition = " AND c_id = '0' ";
  257. break;
  258. case 'all':
  259. $course_condition = " AND c_id IN ('0', '".api_get_course_int_id()."')";
  260. break;
  261. }
  262. $where_condition .= $course_condition;
  263. $order_clause = " ORDER BY title";
  264. $sql .= $where_condition.$order_clause;
  265. $result = Database::query($sql);
  266. if (Database::num_rows($result)) {
  267. return Database::store_result($result, 'ASSOC');
  268. }
  269. return false;
  270. }
  271. /**
  272. * Gets the number of question of category id=in_id
  273. * @todo I'm removing the $in_id parameter because it seems that you're using $this->id instead of $in_id after confirmation delete this
  274. * jmontoya
  275. */
  276. //public function getCategoryQuestionsNumber($in_id) {
  277. public function getCategoryQuestionsNumber()
  278. {
  279. $t_reltable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  280. $in_id = Database::escape_string($this->id);
  281. $sql = "SELECT count(*) AS nb FROM $t_reltable WHERE category_id = $in_id";
  282. $res = Database::query($sql);
  283. if (Database::num_rows($res)) {
  284. $row = Database::fetch_array($res);
  285. return $row['nb'];
  286. }
  287. return 0;
  288. }
  289. public function display($in_color="#E0EBF5")
  290. {
  291. echo "<textarea style='background-color:$in_color; width:60%; height:100px;'>";
  292. print_r($this);
  293. echo "</textarea>";
  294. }
  295. /**
  296. * return an array of all Category objects in the database
  297. * If in_field=="" Return an array of all category objects in the database
  298. * Otherwise, return an array of all in_field value in the database (in_field = id or name or description)
  299. */
  300. public static function getCategoryListInfo($in_field = "", $courseId = null)
  301. {
  302. $courseId = intval($courseId);
  303. $t_cattable = Database :: get_course_table(TABLE_QUIZ_CATEGORY);
  304. $in_field = Database::escape_string($in_field);
  305. $tabres = array();
  306. if ($in_field=="") {
  307. $sql = "SELECT * FROM $t_cattable WHERE c_id = $courseId ORDER BY title ASC";
  308. $res = Database::query($sql);
  309. while ($row = Database::fetch_array($res)) {
  310. $tmpcat = new Testcategory($row['iid'], $row['title'], $row['description'], $row['parent_id']);
  311. $tabres[] = $tmpcat;
  312. }
  313. } else {
  314. $sql = "SELECT $in_field FROM $t_cattable WHERE c_id = $courseId
  315. ORDER BY $in_field ASC";
  316. $res = Database::query($sql);
  317. while ($row = Database::fetch_array($res)) {
  318. $tabres[] = $row[$in_field];
  319. }
  320. }
  321. return $tabres;
  322. }
  323. /**
  324. * Return an array with categories for the question
  325. * @param int $question_id
  326. * @param int $courseId
  327. * @return array
  328. * @assert () === false
  329. */
  330. public static function getCategoryForQuestion($question_id, $courseId = null)
  331. {
  332. $result = array();
  333. if (empty($courseId)) {
  334. $courseId = api_get_course_int_id();
  335. }
  336. $courseId = intval($courseId);
  337. $categoryTable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  338. $question_id = Database::escape_string($question_id);
  339. $sql = "SELECT category_id FROM $categoryTable WHERE question_id = '$question_id' AND c_id = $courseId";
  340. $res = Database::query($sql);
  341. if (Database::num_rows($res) > 0) {
  342. while ($row = Database::fetch_array($res, 'ASSOC')) {
  343. $result[] = $row['category_id'];
  344. }
  345. }
  346. return $result;
  347. }
  348. /**
  349. * @param int $question_id
  350. * @param int $courseId
  351. * @return array
  352. */
  353. public static function getCategoryForQuestionWithCategoryData($question_id, $courseId = null)
  354. {
  355. $result = array(); // result
  356. if (empty($courseId)) {
  357. $courseId = api_get_course_int_id();
  358. }
  359. $courseId = intval($courseId);
  360. $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  361. $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  362. $question_id = Database::escape_string($question_id);
  363. $sql = "SELECT * FROM $t_cattable qc INNER JOIN $table_category c ON (category_id = c.iid) WHERE question_id = '$question_id' AND qc.c_id = $courseId";
  364. $res = Database::query($sql);
  365. if (Database::num_rows($res) > 0) {
  366. while ($row = Database::fetch_array($res, 'ASSOC')) {
  367. $result[] = $row;
  368. }
  369. }
  370. return $result;
  371. }
  372. /**
  373. *
  374. * @param int $question_id
  375. * @param int $course_id
  376. * @param bool $display_into_labels
  377. * @param bool $categoryMinusOne shows category - 1 see BT#6540
  378. * @return string
  379. */
  380. public static function getCategoryNamesForQuestion(
  381. $question_id,
  382. $course_id = null,
  383. $display_into_labels = true,
  384. $categoryMinusOne = false
  385. ) {
  386. if (empty($course_id) || $course_id == "") {
  387. $course_id = api_get_course_int_id();
  388. }
  389. $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  390. $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  391. $question_id = intval($question_id);
  392. $course_id = intval($course_id);
  393. $sql = "SELECT c.title, c.iid FROM $t_cattable qc INNER JOIN $table_category c
  394. ON (qc.category_id = c.iid AND qc.c_id = $course_id)
  395. WHERE question_id = '$question_id' ";
  396. $res = Database::query($sql);
  397. $result = array();
  398. if (Database::num_rows($res) > 0) {
  399. while ($row = Database::fetch_array($res)) {
  400. $cat = new Testcategory($row['iid']);
  401. if ($categoryMinusOne) {
  402. $catParts = explode('>', $cat->parent_path);
  403. if (isset($catParts[0])) {
  404. unset($catParts[0]);
  405. $cat->parent_path = implode('>', $catParts);
  406. }
  407. }
  408. $result[] = array('title' => $cat->parent_path);
  409. }
  410. }
  411. if ($display_into_labels) {
  412. $html = self::draw_category_label($result, 'header');
  413. return $html;
  414. }
  415. return $result;
  416. }
  417. /**
  418. * true if question id has a category
  419. * @assert () === false
  420. * @assert (null) === false
  421. * @assert (-1) === false
  422. */
  423. public static function isQuestionHasCategory($question_id)
  424. {
  425. $category_list = Testcategory::getCategoryForQuestion($question_id);
  426. if (!empty($category_list)) {
  427. return true;
  428. }
  429. return false;
  430. }
  431. /**
  432. * @todo fix this
  433. Return the category name for question with question_id = $in_questionid
  434. In this version, a question has only 1 category.
  435. Return the category id, "" if none
  436. */
  437. public static function getCategoryNameForQuestion($catid, $course_id = null)
  438. {
  439. if (empty($course_id) || $course_id == "") {
  440. $course_id = api_get_course_int_id();
  441. }
  442. $course_id = intval($course_id);
  443. $result = array();
  444. $t_cattable = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  445. $catid = Database::escape_string($catid);
  446. $sql = "SELECT title FROM $t_cattable WHERE iid = '$catid' AND c_id = $course_id";
  447. $res = Database::query($sql);
  448. $data = Database::fetch_array($res);
  449. if (Database::num_rows($res) > 0) {
  450. $result = $data['title'];
  451. }
  452. return $result;
  453. }
  454. /**
  455. * Return the list of different categories ID for a test
  456. * @param int exercise id
  457. * @param bool group category
  458. * @param int course id
  459. * @return array of category id (integer)
  460. * @author hubert.borderiou 07-04-2011, Julio Montoya
  461. */
  462. public static function getListOfCategoriesIDForTest($exercise_id, $grouped_by_category = true, $courseId = null)
  463. {
  464. $exercise = new Exercise($courseId);
  465. $exercise->read($exercise_id, false);
  466. $categories_in_exercise = $exercise->getQuestionWithCategories();
  467. $categories = array();
  468. if (!empty($categories_in_exercise)) {
  469. foreach($categories_in_exercise as $category) {
  470. $category['id'] = $category['iid'];
  471. $categories[$category['iid']] = $category;
  472. }
  473. }
  474. return $categories;
  475. }
  476. /**
  477. * @param Exercise $exercise_obj
  478. * @return array
  479. */
  480. public static function getListOfCategoriesIDForTestObject(Exercise $exercise_obj)
  481. {
  482. $categories_in_exercise = array();
  483. $question_list = $exercise_obj->getQuestionOrderedListByName();
  484. // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ???
  485. foreach ($question_list as $questionInfo) {
  486. $question_id = $questionInfo['question_id'];
  487. $category_list = Testcategory::getCategoryForQuestion($question_id);
  488. if (!empty($category_list)) {
  489. $categories_in_exercise = array_merge($categories_in_exercise, $category_list);
  490. }
  491. }
  492. if (!empty($categories_in_exercise)) {
  493. $categories_in_exercise = array_unique(array_filter($categories_in_exercise));
  494. }
  495. return $categories_in_exercise;
  496. }
  497. /**
  498. * Return the list of different categories NAME for a test
  499. * @param int exercise id
  500. * @param bool $grouped_by_category
  501. * @param int $courseId
  502. * @return array of string
  503. *
  504. * @author function rewrote by jmontoya
  505. */
  506. public static function getListOfCategoriesNameForTest($exercise_id, $grouped_by_category = true, $courseId = null)
  507. {
  508. $result = array();
  509. $categories = self::getListOfCategoriesIDForTest($exercise_id, $grouped_by_category, $courseId);
  510. foreach ($categories as $catInfo) {
  511. $categoryId = $catInfo['iid'];
  512. if (!empty($categoryId)) {
  513. $result[$categoryId] = array(
  514. 'title' => $catInfo['title'],
  515. 'parent_id' => $catInfo['parent_id'],
  516. 'c_id' => $catInfo['c_id']
  517. );
  518. }
  519. }
  520. return $result;
  521. }
  522. /**
  523. * @param Exercise $exercise_obj
  524. * @return array
  525. */
  526. public static function getListOfCategoriesForTest(Exercise $exercise_obj)
  527. {
  528. $result = array();
  529. $categories = self::getListOfCategoriesIDForTestObject($exercise_obj);
  530. foreach ($categories as $cat_id) {
  531. $cat = new Testcategory($cat_id);
  532. $cat = (array)$cat;
  533. $cat['iid'] = $cat['id'];
  534. $cat['title'] = $cat['name'];
  535. $result[$cat['id']] = $cat;
  536. }
  537. return $result;
  538. }
  539. /**
  540. * Return the number of different categories for a test
  541. * input : test_id
  542. * return : integer
  543. * hubert.borderiou 07-04-2011
  544. */
  545. public static function getNumberOfCategoriesForTest($exercise_id)
  546. {
  547. return count(Testcategory::getListOfCategoriesIDForTest($exercise_id));
  548. }
  549. /**
  550. * return the number of question of a category id in a test
  551. * input : test_id, category_id
  552. * return : integer
  553. * hubert.borderiou 07-04-2011
  554. */
  555. public static function getNumberOfQuestionsInCategoryForTest($exercise_id, $category_id)
  556. {
  557. $number_questions_in_category = 0;
  558. $exercise = new Exercise();
  559. $exercise->read($exercise_id);
  560. $question_list = $exercise->getQuestionList();
  561. // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ? ? ?
  562. foreach ($question_list as $question_id) {
  563. $category_in_question = Testcategory::getCategoryForQuestion($question_id);
  564. if (in_array($category_id, $category_in_question)) {
  565. $number_questions_in_category++;
  566. }
  567. }
  568. return $number_questions_in_category;
  569. }
  570. /**
  571. * return the number of question for a test using random by category
  572. * input : test_id, number of random question (min 1)
  573. * hubert.borderiou 07-04-2011
  574. * question witout categories are not counted
  575. */
  576. public static function getNumberOfQuestionRandomByCategory($exercise_id, $in_nbrandom)
  577. {
  578. $nbquestionresult = 0;
  579. $list_categories = Testcategory::getListOfCategoriesIDForTest($exercise_id);
  580. if (!empty($list_categories)) {
  581. foreach ($list_categories as $category_item) {
  582. if ($category_item > 0) {
  583. // 0 = no category for this question
  584. $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($exercise_id, $category_item);
  585. if ($nbQuestionInThisCat > $in_nbrandom) {
  586. $nbquestionresult += $in_nbrandom;
  587. } else {
  588. $nbquestionresult += $nbQuestionInThisCat;
  589. }
  590. }
  591. }
  592. }
  593. return $nbquestionresult;
  594. }
  595. /**
  596. * Return an array (id=>name)
  597. * tabresult[0] = get_lang('NoCategory');
  598. *
  599. */
  600. static function getCategoriesIdAndName($in_courseid = 0)
  601. {
  602. $tabcatobject = Testcategory::getCategoryListInfo("", $in_courseid);
  603. $tabresult = array("0"=>get_lang('NoCategorySelected'));
  604. for ($i=0; $i < count($tabcatobject); $i++) {
  605. $tabresult[$tabcatobject[$i]->id] = $tabcatobject[$i]->name;
  606. }
  607. return $tabresult;
  608. }
  609. /**
  610. * Returns an array of question ids for each category
  611. * $categories[1][30] = 10, array with category id = 1 and question_id = 10
  612. * A question has "n" categories
  613. * @param int $exerciseId
  614. * @param array $check_in_question_list
  615. * @param array $categoriesAddedInExercise
  616. * @param int $courseId
  617. * @return array
  618. */
  619. static function getQuestionsByCat(
  620. $exerciseId,
  621. $check_in_question_list = array(),
  622. $categoriesAddedInExercise = array(),
  623. $courseId = null
  624. ) {
  625. $tableQuestion = Database::get_course_table(TABLE_QUIZ_QUESTION);
  626. $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  627. $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  628. $categoryTable = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  629. $exerciseId = intval($exerciseId);
  630. if (empty($courseId)) {
  631. $courseId = api_get_course_int_id();
  632. } else {
  633. $courseId = intval($courseId);
  634. }
  635. $sql = "SELECT DISTINCT qrc.question_id, qrc.category_id
  636. FROM $TBL_QUESTION_REL_CATEGORY qrc INNER JOIN $TBL_EXERCICE_QUESTION eq
  637. ON (eq.question_id = qrc.question_id)
  638. INNER JOIN $categoryTable c
  639. ON (c.iid = qrc.category_id)
  640. INNER JOIN $tableQuestion q
  641. ON (q.iid = qrc.question_id )
  642. WHERE exercice_id = $exerciseId AND
  643. qrc.c_id = ".$courseId."
  644. ";
  645. $res = Database::query($sql);
  646. $categories = array();
  647. while ($data = Database::fetch_array($res)) {
  648. if (!empty($check_in_question_list)) {
  649. if (!in_array($data['question_id'], $check_in_question_list)) {
  650. continue;
  651. }
  652. }
  653. if (!isset($categories[$data['category_id']]) OR !is_array($categories[$data['category_id']])) {
  654. $categories[$data['category_id']] = array();
  655. }
  656. $categories[$data['category_id']][] = $data['question_id'];
  657. }
  658. $newCategoryList = array();
  659. foreach ($categoriesAddedInExercise as $category) {
  660. $categoryId = $category['category_id'];
  661. if (isset($categories[$categoryId])) {
  662. $newCategoryList[$categoryId] = $categories[$categoryId];
  663. }
  664. }
  665. return $newCategoryList;
  666. }
  667. /**
  668. * Returns an array of question ids for each category
  669. * $categories[1][30] = 10, array with category id = 1 and question_id = 10
  670. * A question has "n" categories
  671. * @param int exercise
  672. * @param array check question list
  673. * @param string order by
  674. * @return array
  675. */
  676. static function getQuestionsByCategory($categoryId) {
  677. $tableQuestion = Database::get_course_table(TABLE_QUIZ_QUESTION);
  678. $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  679. $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  680. $categoryTable = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  681. $categoryId = intval($categoryId);
  682. $sql = "SELECT DISTINCT qrc.question_id, qrc.category_id
  683. FROM $TBL_QUESTION_REL_CATEGORY qrc INNER JOIN $TBL_EXERCICE_QUESTION eq
  684. ON (eq.question_id = qrc.question_id)
  685. INNER JOIN $categoryTable c
  686. ON (c.iid = qrc.category_id)
  687. INNER JOIN $tableQuestion q
  688. ON (q.iid = qrc.question_id )
  689. WHERE qrc.category_id = $categoryId ";
  690. $res = Database::query($sql);
  691. $newCategoryList = array();
  692. while ($data = Database::fetch_array($res)) {
  693. $newCategoryList[] = $data['question_id'];
  694. }
  695. return $newCategoryList;
  696. }
  697. /**
  698. * Return an array of X elements of an array
  699. * @param array $array
  700. * @param int $numberOfElements
  701. * @param bool $randomize
  702. * @return array
  703. */
  704. public static function getNElementsFromArray($array, $numberOfElements, $randomize)
  705. {
  706. if (empty($numberOfElements)) {
  707. return array();
  708. }
  709. if (!empty($array)) {
  710. if ($randomize) {
  711. shuffle($array);
  712. }
  713. if ($numberOfElements < count($array)) {
  714. $array = array_slice($array, 0, $numberOfElements);
  715. }
  716. }
  717. return $array;
  718. }
  719. /**
  720. * Display signs [+] and/or (>0) after question title if question has options
  721. * scoreAlwaysPositive and/or uncheckedMayScore
  722. */
  723. public function displayQuestionOption($in_objQuestion) {
  724. if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->scoreAlwaysPositive) {
  725. echo "<span style='font-size:75%'> (>0)</span>";
  726. }
  727. if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->uncheckedMayScore) {
  728. echo "<span style='font-size:75%'> [+]</span>";
  729. }
  730. }
  731. /**
  732. * key of $array are the category id (0 for not in a category)
  733. * value is the array of question id of this category
  734. * Sort question by Category
  735. */
  736. public static function sortCategoriesQuestionByName($array) {
  737. $tabResult = array();
  738. $category_array = array();
  739. // tab of category name
  740. while (list($cat_id, $tabquestion) = each($array)) {
  741. $cat = new Testcategory($cat_id);
  742. $category_array[$cat_id] = $cat->title;
  743. }
  744. reset($array);
  745. // sort table by value, keeping keys as they are
  746. asort($category_array);
  747. // keys of $tabCatName are keys order for $in_tab
  748. while (list($key, $val) = each($category_array)) {
  749. $tabResult[$key] = $array[$key];
  750. }
  751. return $tabResult;
  752. }
  753. /**
  754. * Return total score for test exe_id for all question in the category $in_cat_id for user
  755. * If no question for this category, return ""
  756. */
  757. public static function getCatScoreForExeidForUserid($in_cat_id, $in_exe_id, $in_user_id)
  758. {
  759. $tbl_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
  760. $tbl_question_rel_category = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  761. $in_cat_id = intval($in_cat_id);
  762. $in_exe_id = intval($in_exe_id);
  763. $in_user_id = intval($in_user_id);
  764. $query = "SELECT DISTINCT marks, exe_id, user_id, ta.question_id, category_id
  765. FROM $tbl_track_attempt ta , $tbl_question_rel_category qrc
  766. WHERE ta.question_id = qrc.question_id AND qrc.category_id=$in_cat_id AND exe_id = $in_exe_id AND user_id = $in_user_id";
  767. $res = Database::query($query);
  768. $totalcatscore = "";
  769. while ($data = Database::fetch_array($res)) {
  770. $totalcatscore += $data['marks'];
  771. }
  772. return $totalcatscore;
  773. }
  774. /**
  775. * return the number max of question in a category
  776. * count the number of questions in all categories, and return the max
  777. * @author - hubert borderiou
  778. */
  779. public static function getNumberMaxQuestionByCat($in_testid)
  780. {
  781. $res_num_max = 0;
  782. // foreach question
  783. $tabcatid = Testcategory::getListOfCategoriesIDForTest($in_testid);
  784. for ($i=0; $i < count($tabcatid); $i++) {
  785. if ($tabcatid[$i] > 0) { // 0 = no category for this question
  786. $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($in_testid, $tabcatid[$i]);
  787. if ($nbQuestionInThisCat > $res_num_max) {
  788. $res_num_max = $nbQuestionInThisCat;
  789. }
  790. }
  791. }
  792. return $res_num_max;
  793. }
  794. /**
  795. * @param int $course_id
  796. * @return array
  797. */
  798. public static function getCategoryListName($course_id = null)
  799. {
  800. $category_list = self::getCategoryListInfo(null, $course_id);
  801. $category_name_list = array();
  802. if (!empty($category_list)) {
  803. foreach ($category_list as $category) {
  804. $category_name_list[$category->id] = $category->name;
  805. }
  806. }
  807. return $category_name_list;
  808. }
  809. /**
  810. * @param array $category_list
  811. * @param array $all_categories
  812. * @return null|string
  813. */
  814. public static function return_category_labels($category_list, $all_categories)
  815. {
  816. $category_list_to_render = array();
  817. foreach ($category_list as $category_id) {
  818. $category_name = null;
  819. if (!isset($all_categories[$category_id])) {
  820. $category_name = get_lang('Untitled');
  821. $parentId = null;
  822. $cId = null;
  823. } else {
  824. $parentId = $all_categories[$category_id]['parent_id'];
  825. $cId = $all_categories[$category_id]['c_id'];
  826. $category_name = $all_categories[$category_id]['title'];
  827. }
  828. $category_list_to_render[] = array(
  829. 'title' => $category_name,
  830. 'parent_id' => $parentId,
  831. 'c_id' => $cId
  832. );
  833. }
  834. $html = self::draw_category_label($category_list_to_render, 'label');
  835. return $html;
  836. }
  837. /**
  838. * @param array $category_list
  839. * @param string $type
  840. * @return null|string
  841. */
  842. public static function draw_category_label($category_list, $type = 'label') {
  843. $new_category_list = array();
  844. foreach ($category_list as $category) {
  845. $category_name = $category['title'];
  846. $category_name_cut = Text::cut($category['title'], 20);
  847. switch ($type) {
  848. case 'label':
  849. // Global cat
  850. /*
  851. $parentId = isset($category['parent_id']) && !empty($category['parent_id']) ? $category['parent_id'] : null;
  852. if (empty($parentId)) {
  853. $new_category_list[] = Display::label($category_name, 'info');
  854. } else {
  855. // Local cat
  856. $new_category_list[] = Display::label($category_name, 'success');
  857. }*/
  858. $courseId = isset($category['c_id']) && !empty($category['c_id']) ? $category['c_id'] : null;
  859. if (empty($courseId)) {
  860. $new_category_list[] = Display::label($category_name_cut, 'info', $category_name);
  861. } else {
  862. // Local cat
  863. $new_category_list[] = Display::label($category_name_cut, 'success', $category_name);
  864. }
  865. break;
  866. case 'header':
  867. $new_category_list[] = $category_name;
  868. break;
  869. }
  870. }
  871. $html = null;
  872. if (!empty($new_category_list)) {
  873. switch ($type) {
  874. case 'label':
  875. $html = implode(' ', $new_category_list);
  876. break;
  877. case 'header':
  878. $html = Display::page_subheader3(get_lang('Category').': '.implode(', ', $new_category_list));
  879. break;
  880. }
  881. }
  882. return $html;
  883. }
  884. /**
  885. * Returns a category summary report
  886. *
  887. * @param int exercise id
  888. * @param int course id
  889. * @param array pre-filled array with the category_id, score, and weight example: array(1 => array('score' => '10', 'total' => 20));
  890. * @param bool $categoryMinusOne shows category - 1 see BT#6540
  891. * @param bool $returnArray
  892. * @return string
  893. */
  894. public static function get_stats_table_by_attempt(
  895. $exercise_id,
  896. $courseId,
  897. $category_list = array(),
  898. $categoryMinusOne = false,
  899. $returnArray = false
  900. ) {
  901. if (empty($category_list)) {
  902. return null;
  903. }
  904. $table = new HTML_Table(array('class' => 'data_table'));
  905. $table->setHeaderContents(0, 0, get_lang('Categories'));
  906. $table->setHeaderContents(0, 1, get_lang('AbsoluteScore'));
  907. $table->setHeaderContents(0, 2, get_lang('RelativeScore'));
  908. $row = 1;
  909. $none_category = array();
  910. if (isset($category_list['none'])) {
  911. $none_category = $category_list['none'];
  912. unset($category_list['none']);
  913. }
  914. $total = array();
  915. if (isset($category_list['total'])) {
  916. $total = $category_list['total'];
  917. unset($category_list['total']);
  918. }
  919. $content = array();
  920. if (!empty($category_list) && count($category_list) > 1) {
  921. $globalCategoryScore = self::globalizeCategories($exercise_id, $courseId, $category_list, $categoryMinusOne);
  922. foreach ($globalCategoryScore as $category_id => $category_item) {
  923. $category_item['category_id'] = $category_id;
  924. $content[$row] = $category_item;
  925. $table->setCellContents($row, 0, $category_item['title']);
  926. $table->setCellContents($row, 1, ExerciseLib::show_score($category_item['score'], $category_item['total'], false));
  927. $table->setCellContents($row, 2, ExerciseLib::show_score($category_item['score'], $category_item['total'], true, false, true));
  928. $class = 'class="row_odd"';
  929. if ($row % 2) {
  930. $class = 'class="row_even"';
  931. }
  932. $table->setRowAttributes($row, $class, true);
  933. $row++;
  934. }
  935. if (!empty($none_category)) {
  936. $content[$row] = $none_category;
  937. $table->setCellContents($row, 0, get_lang('None'));
  938. $table->setCellContents($row, 1, ExerciseLib::show_score($none_category['score'], $none_category['total'], false));
  939. $table->setCellContents($row, 2, ExerciseLib::show_score($none_category['score'], $none_category['total'], true, false, true));
  940. $row++;
  941. }
  942. if (!empty($total)) {
  943. $total['title'] = 'Total';
  944. $content[$row] = $total;
  945. $table->setCellContents($row, 0, get_lang('Total'));
  946. $table->setCellContents($row, 1, ExerciseLib::show_score($total['score'], $total['total'], false));
  947. $table->setCellContents($row, 2, ExerciseLib::show_score($total['score'], $total['total'], true, false, true));
  948. $table->setRowAttributes($row, 'class="row_total"', true);
  949. }
  950. if ($returnArray) {
  951. return $content;
  952. }
  953. return $table->toHtml();
  954. }
  955. return null;
  956. }
  957. /**
  958. * @param int $exercise_id
  959. * @param int course id
  960. * @param array $category_list
  961. * @param $categoryMinusOne
  962. * @param bool load children
  963. * @return array
  964. */
  965. public static function globalizeCategories($exercise_id, $courseId, $category_list, $categoryMinusOne, $loadChildren = false)
  966. {
  967. global $app;
  968. $category_name_list = Testcategory::getListOfCategoriesNameForTest($exercise_id, false, $courseId);
  969. $em = $app['orm.em'];
  970. /** @var Gedmo\Tree\Entity\Repository\NestedTreeRepository $repo */
  971. $repo = $em->getRepository('Entity\CQuizCategory');
  972. $globalCategoryScore = array();
  973. foreach ($category_list as $category_id => $category_item) {
  974. /** @var Entity\CQuizCategory $cat */
  975. $cat = $em->find('Entity\CQuizCategory', $category_id);
  976. if (empty($cat)) {
  977. continue;
  978. }
  979. $path = $repo->getPath($cat);
  980. if ($loadChildren) {
  981. //$globalCategoryScore[$category_id]['children'] = $repo->getChildren($cat);
  982. //$globalCategoryScore[$category_id]['children'] = $path;
  983. }
  984. $categoryName = $category_name_list[$category_id];
  985. //$categoryName = $category_item['name'];
  986. $index = 0;
  987. if ($categoryMinusOne) {
  988. $index = 1;
  989. }
  990. if (isset($path[$index])) {
  991. $category_id = $path[$index]->getIid();
  992. $categoryName = $path[$index]->getTitle();
  993. }
  994. if (!isset($globalCategoryScore[$category_id])) {
  995. $globalCategoryScore[$category_id] = array();
  996. $globalCategoryScore[$category_id]['score'] = 0;
  997. $globalCategoryScore[$category_id]['total'] = 0;
  998. $globalCategoryScore[$category_id]['title'] = '';
  999. }
  1000. if (isset($category_item['score'])) {
  1001. $globalCategoryScore[$category_id]['score'] += $category_item['score'];
  1002. }
  1003. if (isset($category_item['total'])) {
  1004. $globalCategoryScore[$category_id]['total'] += $category_item['total'];
  1005. }
  1006. if (isset($categoryName)) {
  1007. $globalCategoryScore[$category_id]['title'] = $categoryName;
  1008. }
  1009. }
  1010. return $globalCategoryScore;
  1011. }
  1012. /**
  1013. * @return array
  1014. */
  1015. function get_all_categories()
  1016. {
  1017. $table = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  1018. $sql = "SELECT * FROM $table ORDER BY title ASC";
  1019. $res = Database::query($sql);
  1020. while ($row = Database::fetch_array($res,'ASSOC')) {
  1021. $array[] = $row;
  1022. }
  1023. return $array;
  1024. }
  1025. /**
  1026. * @param int $exercise_id
  1027. * @param int $course_id
  1028. * @param string $order
  1029. * @param bool shuffle
  1030. * @param bool $excludeCategoryWithNoQuestions
  1031. * @param bool $shuffleSubcategories
  1032. * @param array
  1033. * @return array
  1034. */
  1035. public function getCategoryExerciseTree(
  1036. $exercise_id,
  1037. $course_id,
  1038. $order = null,
  1039. $shuffle = false,
  1040. $excludeCategoryWithNoQuestions = true,
  1041. $shuffleSubcategories = false,
  1042. $categoryList = array()
  1043. ) {
  1044. if (empty($categoryList)) {
  1045. $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY);
  1046. $table_category = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  1047. $sql = "SELECT * FROM $table qc INNER JOIN $table_category c ON (category_id = c.iid)
  1048. WHERE exercise_id = {$exercise_id} ";
  1049. if (!empty($order)) {
  1050. $sql .= "ORDER BY $order";
  1051. }
  1052. $categories = array();
  1053. $result = Database::query($sql);
  1054. if (Database::num_rows($result)) {
  1055. while ($row = Database::fetch_array($result, 'ASSOC')) {
  1056. if ($excludeCategoryWithNoQuestions) {
  1057. if ($row['count_questions'] == 0) {
  1058. continue;
  1059. }
  1060. }
  1061. $categories[$row['category_id']] = $row;
  1062. }
  1063. }
  1064. } else {
  1065. $categories = $categoryList;
  1066. }
  1067. // Shuffle sub categories.
  1068. if ($shuffleSubcategories) {
  1069. $categoriesByParent = array();
  1070. foreach ($categories as $cat) {
  1071. $categoriesByParent[$cat['parent_id']][] = $cat;
  1072. }
  1073. if (!empty($categoriesByParent)) {
  1074. foreach ($categoriesByParent as &$categoryList) {
  1075. ArrayClass::shuffle_assoc($categoryList);
  1076. }
  1077. $newCategoryList = array();
  1078. foreach ($categoriesByParent as $categoryListToOrder) {
  1079. foreach ($categoryListToOrder as $categoryItem) {
  1080. $newCategoryList[$categoryItem['iid']] = $categoryItem;
  1081. }
  1082. }
  1083. $categories = $newCategoryList;
  1084. }
  1085. }
  1086. if ($shuffle) {
  1087. ArrayClass::shuffle_assoc($categories);
  1088. }
  1089. return $categories;
  1090. }
  1091. /**
  1092. * Returns the category form.
  1093. * @param Exercise $exercise_obj
  1094. * @return string
  1095. */
  1096. public function returnCategoryForm(Exercise $exercise_obj)
  1097. {
  1098. $categories = $this->getListOfCategoriesForTest($exercise_obj);
  1099. $saved_categories = $exercise_obj->get_categories_in_exercise();
  1100. $return = null;
  1101. if (!empty($categories)) {
  1102. $nbQuestionsTotal = $exercise_obj->getNumberQuestionExerciseCategory();
  1103. $exercise_obj->setCategoriesGrouping(true);
  1104. $real_question_count = count($exercise_obj->getQuestionList());
  1105. $warning = null;
  1106. if ($nbQuestionsTotal != $real_question_count) {
  1107. $warning = Display::return_message(get_lang('CheckThatYouHaveEnoughQuestionsInYourCategories'), 'warning');
  1108. }
  1109. $return .= $warning;
  1110. $return .= '<table class="data_table">';
  1111. $return .= '<tr>';
  1112. $return .= '<th height="24">' . get_lang('Categories') . '</th>';
  1113. $return .= '<th width="70" height="24">' . get_lang('Number') . '</th></tr>';
  1114. $orderedCategoryList = array();
  1115. foreach ($categories as $category) {
  1116. $orderedCategoryList[$category['iid']] = $category['parent_path'];
  1117. }
  1118. natsort($orderedCategoryList);
  1119. foreach ($orderedCategoryList as $categoryId => $path) {
  1120. $category = $categories[$categoryId];
  1121. $cat_id = $category['iid'];
  1122. $return .= '<tr>';
  1123. $return .= '<td>';
  1124. $return .= Display::div($category['parent_path']);
  1125. $return .= '</td>';
  1126. $return .= '<td>';
  1127. $value = isset($saved_categories) && isset($saved_categories[$cat_id]) ? $saved_categories[$cat_id]['count_questions'] : -1;
  1128. $return .= '<input name="category['.$cat_id.']" value="' .$value.'" />';
  1129. $return .= '</td>';
  1130. $return .= '</tr>';
  1131. }
  1132. $return .= '</table>';
  1133. $return .= get_lang('ZeroMeansNoQuestionWillBeSelectedMinusOneMeansThatAllQuestionsWillBeSelected');
  1134. return $return;
  1135. }
  1136. }
  1137. /**
  1138. * Sorts an array
  1139. * @param $array
  1140. * @return mixed
  1141. */
  1142. public function sort_tree_array($array)
  1143. {
  1144. foreach ($array as $key => $row) {
  1145. $parent[$key] = $row['parent_id'];
  1146. }
  1147. if (count($array) > 0) {
  1148. array_multisort($parent, SORT_ASC, $array);
  1149. }
  1150. return $array;
  1151. }
  1152. /**
  1153. * @param FormValidator $form
  1154. * @param string $action
  1155. */
  1156. public function getForm(& $form, $action = 'new') {
  1157. switch($action) {
  1158. case 'new':
  1159. $header = get_lang('AddACategory');
  1160. $submit = get_lang('AddTestCategory');
  1161. break;
  1162. case 'edit':
  1163. $header = get_lang('EditCategory');
  1164. $submit = get_lang('ModifyCategory');
  1165. break;
  1166. }
  1167. // setting the form elements
  1168. $form->addElement('header', $header);
  1169. $form->addElement('hidden', 'category_id');
  1170. $form->addElement('text', 'category_name', get_lang('CategoryName'), array('class' => 'span6'));
  1171. $form->add_html_editor('category_description', get_lang('CategoryDescription'), false, false, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200'));
  1172. $category_parent_list = array();
  1173. $options = array(
  1174. '' => get_lang('SelectAnOption'),
  1175. '1' => get_lang('Visible'),
  1176. '0' => get_lang('Hidden')
  1177. );
  1178. $form->addElement('select', 'visibility', get_lang('Visibility'), $options);
  1179. $script = null;
  1180. if (!empty($this->parent_id)) {
  1181. $parent_cat = new Testcategory($this->parent_id);
  1182. $category_parent_list = array($parent_cat->id => $parent_cat->name);
  1183. $script .= '<script>$(function() { $("#parent_id").trigger("addItem",[{"title": "'.$parent_cat->name.'", "value": "'.$parent_cat->id.'"}]); });</script>';
  1184. }
  1185. $form->addElement('html', $script);
  1186. $form->addElement('select', 'parent_id', get_lang('Parent'), $category_parent_list, array('id' => 'parent_id'));
  1187. $form->addElement('style_submit_button', 'SubmitNote', $submit, 'class="add"');
  1188. // setting the defaults
  1189. $defaults = array();
  1190. $defaults["category_id"] = $this->id;
  1191. $defaults["category_name"] = $this->name;
  1192. $defaults["category_description"] = $this->description;
  1193. $defaults["parent_id"] = $this->parent_id;
  1194. $defaults["visibility"] = $this->visibility;
  1195. $form->setDefaults($defaults);
  1196. // setting the rules
  1197. $form->addRule('category_name', get_lang('ThisFieldIsRequired'), 'required');
  1198. }
  1199. /**
  1200. * Checks whether a category is global or not
  1201. * @param int $categoryId
  1202. * @return bool True if it is global, false otherwise
  1203. * @assert (0) == false
  1204. */
  1205. function isGlobal($categoryId)
  1206. {
  1207. $categoryTable = Database::get_course_table(TABLE_QUIZ_CATEGORY);
  1208. $sql = "SELECT parent_id, c_id FROM $categoryTable WHERE iid = $categoryId";
  1209. $res = Database::query($sql);
  1210. if (Database::num_rows($res) < 1) {
  1211. return false;
  1212. }
  1213. $row = Database::fetch_assoc($res);
  1214. $global = ($row['c_id'] == 0 ? true : false);
  1215. return $global;
  1216. }
  1217. /**
  1218. * @param array $questionList
  1219. * @param int $courseId
  1220. * @return array
  1221. */
  1222. public static function getCategoriesFromQuestionList($questionList, $courseId, $multipleCategoriesAllowed = false)
  1223. {
  1224. $categories = array();
  1225. foreach ($questionList as $questionId) {
  1226. $categoryList = self::getCategoryForQuestionWithCategoryData($questionId, $courseId);
  1227. foreach ($categoryList as $categoryData) {
  1228. if ($multipleCategoriesAllowed) {
  1229. $categories[] = array(
  1230. 'categoryId' => $categoryData['iid'],
  1231. 'questionId' => $questionId
  1232. );
  1233. } else {
  1234. $categories[$categoryData['iid']][] = $questionId;
  1235. }
  1236. }
  1237. }
  1238. return $categories;
  1239. }
  1240. }