1 | <?php |
||
2 | |||
3 | /* For licensing terms, see /license.txt */ |
||
4 | |||
5 | use ChamiloSession as Session; |
||
6 | |||
7 | /** |
||
8 | * Class TestCategory. |
||
9 | * Manage question categories inside an exercise. |
||
10 | * |
||
11 | * @author hubert.borderiou |
||
12 | * @author Julio Montoya - several fixes |
||
13 | * |
||
14 | * @todo rename to ExerciseCategory |
||
15 | */ |
||
16 | class TestCategory |
||
17 | { |
||
18 | public $iid; |
||
19 | public $name; |
||
20 | public $description; |
||
21 | |||
22 | /** |
||
23 | * Constructor of the class Category. |
||
24 | */ |
||
25 | public function __construct() |
||
26 | { |
||
27 | $this->name = ''; |
||
28 | $this->description = ''; |
||
29 | } |
||
30 | |||
31 | /** |
||
32 | * return the TestCategory object with iid=$id. |
||
33 | * |
||
34 | * @param int $id |
||
35 | * @param int $courseId |
||
36 | * |
||
37 | * @return TestCategory |
||
38 | */ |
||
39 | public function getCategory($id, $courseId = 0) |
||
40 | { |
||
41 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
42 | $id = (int) $id; |
||
43 | $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId; |
||
44 | $sql = "SELECT * FROM $table |
||
45 | WHERE iid = ".$id; |
||
46 | $res = Database::query($sql); |
||
47 | |||
48 | if (Database::num_rows($res)) { |
||
49 | $row = Database::fetch_array($res); |
||
50 | |||
51 | $this->iid = $row['iid']; |
||
52 | $this->name = $row['title']; |
||
53 | $this->description = $row['description']; |
||
54 | |||
55 | return $this; |
||
56 | } |
||
57 | |||
58 | return false; |
||
59 | } |
||
60 | |||
61 | /** |
||
62 | * Save TestCategory in the database if name doesn't exists. |
||
63 | * |
||
64 | * @param int $courseId |
||
65 | * |
||
66 | * @return bool |
||
67 | */ |
||
68 | public function save($courseId = 0) |
||
69 | { |
||
70 | $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId; |
||
71 | $courseInfo = api_get_course_info_by_id($courseId); |
||
72 | if (empty($courseInfo)) { |
||
73 | return false; |
||
74 | } |
||
75 | |||
76 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
77 | |||
78 | // check if name already exists |
||
79 | $sql = "SELECT count(*) AS nb FROM $table |
||
80 | WHERE title = '".Database::escape_string($this->name)."' AND c_id = $courseId"; |
||
81 | $result = Database::query($sql); |
||
82 | $row = Database::fetch_array($result); |
||
83 | // lets add in BDD if not the same name |
||
84 | if ($row['nb'] <= 0) { |
||
85 | $params = [ |
||
86 | 'c_id' => $courseId, |
||
87 | 'title' => $this->name, |
||
88 | 'description' => $this->description, |
||
89 | ]; |
||
90 | $newId = Database::insert($table, $params); |
||
91 | |||
92 | if ($newId) { |
||
93 | api_item_property_update( |
||
94 | $courseInfo, |
||
95 | TOOL_TEST_CATEGORY, |
||
96 | $newId, |
||
97 | 'TestCategoryAdded', |
||
98 | api_get_user_id() |
||
99 | ); |
||
100 | } |
||
101 | |||
102 | return $newId; |
||
103 | } else { |
||
104 | return false; |
||
105 | } |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Removes the category from the database |
||
110 | * if there were question in this category, the link between question and category is removed. |
||
111 | * |
||
112 | * @param int $id |
||
113 | * |
||
114 | * @return bool |
||
115 | */ |
||
116 | public function removeCategory($id) |
||
117 | { |
||
118 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
119 | $tbl_question_rel_cat = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); |
||
120 | $id = (int) $id; |
||
121 | $course_id = api_get_course_int_id(); |
||
122 | $category = $this->getCategory($id); |
||
123 | |||
124 | if ($category) { |
||
125 | $sql = "DELETE FROM $table |
||
126 | WHERE iid = ".$id; |
||
127 | Database::query($sql); |
||
128 | |||
129 | // remove link between question and category |
||
130 | $sql = "DELETE FROM $tbl_question_rel_cat |
||
131 | WHERE category_id = ".$id; |
||
132 | Database::query($sql); |
||
133 | // item_property update |
||
134 | $courseInfo = api_get_course_info_by_id($course_id); |
||
135 | api_item_property_update( |
||
136 | $courseInfo, |
||
137 | TOOL_TEST_CATEGORY, |
||
138 | $this->iid, |
||
139 | 'TestCategoryDeleted', |
||
140 | api_get_user_id() |
||
141 | ); |
||
142 | |||
143 | return true; |
||
144 | } |
||
145 | |||
146 | return false; |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Modify category name or description of category with id=in_id. |
||
151 | * |
||
152 | * @param int $courseId |
||
153 | * |
||
154 | * @return bool |
||
155 | */ |
||
156 | public function modifyCategory($courseId = 0) |
||
157 | { |
||
158 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
159 | $id = (int) $this->iid; |
||
160 | $name = Database::escape_string($this->name); |
||
161 | $description = Database::escape_string($this->description); |
||
162 | $cat = $this->getCategory($id, $courseId); |
||
163 | $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId; |
||
164 | $courseInfo = api_get_course_info_by_id($courseId); |
||
165 | if (empty($courseInfo)) { |
||
166 | return false; |
||
167 | } |
||
168 | |||
169 | if ($cat) { |
||
170 | $sql = "UPDATE $table SET |
||
171 | title = '$name', |
||
172 | description = '$description' |
||
173 | WHERE iid = $id"; |
||
174 | Database::query($sql); |
||
175 | |||
176 | api_item_property_update( |
||
177 | $courseInfo, |
||
178 | TOOL_TEST_CATEGORY, |
||
179 | $this->iid, |
||
180 | 'TestCategoryModified', |
||
181 | api_get_user_id() |
||
182 | ); |
||
183 | |||
184 | return true; |
||
185 | } |
||
186 | |||
187 | return false; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Gets the number of question of category id=in_id. |
||
192 | */ |
||
193 | public function getCategoryQuestionsNumber() |
||
194 | { |
||
195 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); |
||
196 | $id = (int) $this->iid; |
||
197 | $sql = "SELECT count(*) AS nb |
||
198 | FROM $table |
||
199 | WHERE category_id = $id AND c_id = ".api_get_course_int_id(); |
||
200 | $res = Database::query($sql); |
||
201 | $row = Database::fetch_array($res); |
||
202 | |||
203 | return $row['nb']; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * Return an array of all Category objects in the database |
||
208 | * If $field=="" Return an array of all category objects in the database |
||
209 | * Otherwise, return an array of all in_field value |
||
210 | * in the database (in_field = id or name or description). |
||
211 | * |
||
212 | * @param string $field |
||
213 | * @param int $courseId |
||
214 | * |
||
215 | * @return array |
||
216 | */ |
||
217 | public static function getCategoryListInfo($field = '', $courseId = 0) |
||
218 | { |
||
219 | $courseId = empty($courseId) ? api_get_course_int_id() : (int) $courseId; |
||
220 | |||
221 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
222 | $categories = []; |
||
223 | if (empty($field)) { |
||
224 | $sql = "SELECT iid FROM $table |
||
225 | WHERE c_id = $courseId |
||
226 | ORDER BY title ASC"; |
||
227 | $res = Database::query($sql); |
||
228 | while ($row = Database::fetch_array($res)) { |
||
229 | $category = new TestCategory(); |
||
230 | $categories[] = $category->getCategory($row['iid'], $courseId); |
||
231 | } |
||
232 | } else { |
||
233 | $field = Database::escape_string($field); |
||
234 | $sql = "SELECT $field FROM $table |
||
235 | WHERE c_id = $courseId |
||
236 | ORDER BY `$field` ASC"; |
||
237 | $res = Database::query($sql); |
||
238 | while ($row = Database::fetch_array($res)) { |
||
239 | $categories[] = $row[$field]; |
||
240 | } |
||
241 | } |
||
242 | |||
243 | return $categories; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * Return the TestCategory id for question with question_id = $questionId |
||
248 | * In this version, a question has only 1 TestCategory. |
||
249 | * Return the TestCategory id, 0 if none. |
||
250 | * |
||
251 | * @param int $questionId |
||
252 | * @param int $courseId |
||
253 | * |
||
254 | * @return int |
||
255 | */ |
||
256 | public static function getCategoryForQuestion($questionId, $courseId = 0) |
||
257 | { |
||
258 | $categoryInfo = self::getCategoryInfoForQuestion($questionId, $courseId); |
||
259 | |||
260 | if (!empty($categoryInfo) && isset($categoryInfo['category_id'])) { |
||
261 | return (int) $categoryInfo['category_id']; |
||
262 | } |
||
263 | |||
264 | return 0; |
||
265 | } |
||
266 | |||
267 | public static function getCategoryInfoForQuestion($questionId, $courseId = 0) |
||
268 | { |
||
269 | $courseId = (int) $courseId; |
||
270 | $questionId = (int) $questionId; |
||
271 | |||
272 | if (empty($courseId)) { |
||
273 | $courseId = api_get_course_int_id(); |
||
274 | } |
||
275 | |||
276 | if (empty($courseId) || empty($questionId)) { |
||
277 | return 0; |
||
278 | } |
||
279 | |||
280 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); |
||
281 | $sql = "SELECT * |
||
282 | FROM $table |
||
283 | WHERE question_id = $questionId AND c_id = $courseId"; |
||
284 | $res = Database::query($sql); |
||
285 | if (Database::num_rows($res) > 0) { |
||
286 | return Database::fetch_array($res, 'ASSOC'); |
||
287 | } |
||
288 | |||
289 | return []; |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * Return the category name for question with question_id = $questionId |
||
294 | * In this version, a question has only 1 category. |
||
295 | * |
||
296 | * @param $questionId |
||
297 | * @param int $courseId |
||
298 | * |
||
299 | * @return string |
||
300 | */ |
||
301 | public static function getCategoryNameForQuestion($questionId, $courseId = 0) |
||
302 | { |
||
303 | if (empty($courseId)) { |
||
304 | $courseId = api_get_course_int_id(); |
||
305 | } |
||
306 | $courseId = (int) $courseId; |
||
307 | $categoryId = self::getCategoryForQuestion($questionId, $courseId); |
||
308 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
309 | $sql = "SELECT title |
||
310 | FROM $table |
||
311 | WHERE iid = $categoryId"; |
||
312 | $res = Database::query($sql); |
||
313 | $data = Database::fetch_array($res); |
||
314 | $result = ''; |
||
315 | if (Database::num_rows($res) > 0) { |
||
316 | $result = $data['title']; |
||
317 | } |
||
318 | |||
319 | return $result; |
||
320 | } |
||
321 | |||
322 | /** |
||
323 | * Return the list of different categories ID for a test in the current course |
||
324 | * hubert.borderiou 07-04-2011. |
||
325 | * |
||
326 | * @param int $exerciseId |
||
327 | * @param int $courseId |
||
328 | * |
||
329 | * @return array |
||
330 | */ |
||
331 | public static function getListOfCategoriesIDForTest($exerciseId, $courseId = 0) |
||
332 | { |
||
333 | // Check test questions, obtaining unique categories in a table |
||
334 | $exercise = new Exercise($courseId); |
||
335 | $exercise->read($exerciseId, false); |
||
336 | $categoriesInExercise = $exercise->getQuestionWithCategories(); |
||
337 | // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ??? |
||
338 | $categories = []; |
||
339 | if (!empty($categoriesInExercise)) { |
||
340 | foreach ($categoriesInExercise as $category) { |
||
341 | $categories[$category['iid']] = $category; |
||
342 | } |
||
343 | } |
||
344 | |||
345 | return $categories; |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * @return array |
||
350 | */ |
||
351 | public static function getListOfCategoriesIDForTestObject(Exercise $exercise) |
||
352 | { |
||
353 | // Check the categories of a test, obtaining unique categories in table |
||
354 | $categories_in_exercise = []; |
||
355 | $question_list = $exercise->getQuestionOrderedListByName(); |
||
356 | |||
357 | // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ??? |
||
358 | foreach ($question_list as $questionInfo) { |
||
359 | $question_id = $questionInfo['question_id']; |
||
360 | $category_list = self::getCategoryForQuestion($question_id); |
||
361 | if (is_numeric($category_list)) { |
||
362 | $category_list = [$category_list]; |
||
363 | } |
||
364 | |||
365 | if (!empty($category_list)) { |
||
366 | $categories_in_exercise = array_merge($categories_in_exercise, $category_list); |
||
367 | } |
||
368 | } |
||
369 | if (!empty($categories_in_exercise)) { |
||
370 | $categories_in_exercise = array_unique(array_filter($categories_in_exercise)); |
||
371 | } |
||
372 | |||
373 | return $categories_in_exercise; |
||
374 | } |
||
375 | |||
376 | /** |
||
377 | * Return the list of different categories NAME for a test. |
||
378 | * |
||
379 | * @param int $exerciseId |
||
380 | * @param bool |
||
381 | * |
||
382 | * @return array |
||
383 | * |
||
384 | * @author function rewrote by jmontoya |
||
385 | */ |
||
386 | public static function getListOfCategoriesNameForTest($exerciseId, $grouped_by_category = true) |
||
387 | { |
||
388 | $result = []; |
||
389 | $categories = self::getListOfCategoriesIDForTest($exerciseId); |
||
390 | |||
391 | foreach ($categories as $catInfo) { |
||
392 | $categoryId = $catInfo['iid']; |
||
393 | if (!empty($categoryId)) { |
||
394 | $result[$categoryId] = [ |
||
395 | 'iid' => $categoryId, |
||
396 | 'title' => $catInfo['title'], |
||
397 | //'parent_id' => $catInfo['parent_id'], |
||
398 | 'parent_id' => '', |
||
399 | 'c_id' => $catInfo['c_id'], |
||
400 | ]; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | return $result; |
||
405 | } |
||
406 | |||
407 | /** |
||
408 | * @return array |
||
409 | */ |
||
410 | public static function getListOfCategoriesForTest(Exercise $exercise) |
||
411 | { |
||
412 | $result = []; |
||
413 | $categories = self::getListOfCategoriesIDForTestObject($exercise); |
||
414 | foreach ($categories as $cat_id) { |
||
415 | $cat = new TestCategory(); |
||
416 | //Todo remove this weird array casting |
||
417 | $cat = (array) $cat->getCategory($cat_id); |
||
418 | $cat['title'] = $cat['name']; |
||
419 | $result[$cat['iid']] = $cat; |
||
420 | } |
||
421 | |||
422 | return $result; |
||
423 | } |
||
424 | |||
425 | /** |
||
426 | * return the number of question of a category id in a test. |
||
427 | * |
||
428 | * @param int $exerciseId |
||
429 | * @param int $categoryId |
||
430 | * |
||
431 | * @return int |
||
432 | * |
||
433 | * @author hubert.borderiou 07-04-2011 |
||
434 | */ |
||
435 | public static function getNumberOfQuestionsInCategoryForTest($exerciseId, $categoryId) |
||
436 | { |
||
437 | $nbCatResult = 0; |
||
438 | $quiz = new Exercise(); |
||
439 | $quiz->read($exerciseId); |
||
440 | $questionList = $quiz->selectQuestionList(); |
||
441 | // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ? ? ? |
||
442 | for ($i = 1; $i <= count($questionList); $i++) { |
||
0 ignored issues
–
show
|
|||
443 | if (self::getCategoryForQuestion($questionList[$i]) == $categoryId) { |
||
444 | $nbCatResult++; |
||
445 | } |
||
446 | } |
||
447 | |||
448 | return $nbCatResult; |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * return the number of question for a test using random by category |
||
453 | * input : test_id, number of random question (min 1). |
||
454 | * |
||
455 | * @param int $exerciseId |
||
456 | * @param int $random |
||
457 | * |
||
458 | * @return int |
||
459 | * hubert.borderiou 07-04-2011 |
||
460 | * question without categories are not counted |
||
461 | */ |
||
462 | public static function getNumberOfQuestionRandomByCategory($exerciseId, $random) |
||
463 | { |
||
464 | $count = 0; |
||
465 | $categories = self::getListOfCategoriesIDForTest($exerciseId); |
||
466 | foreach ($categories as $category) { |
||
467 | if (empty($category['iid'])) { |
||
468 | continue; |
||
469 | } |
||
470 | |||
471 | $nbQuestionInThisCat = self::getNumberOfQuestionsInCategoryForTest( |
||
472 | $exerciseId, |
||
473 | $category['iid'] |
||
474 | ); |
||
475 | |||
476 | if ($nbQuestionInThisCat > $random) { |
||
477 | $count += $random; |
||
478 | } else { |
||
479 | $count += $nbQuestionInThisCat; |
||
480 | } |
||
481 | } |
||
482 | |||
483 | return $count; |
||
484 | } |
||
485 | |||
486 | /** |
||
487 | * Return an array (id=>name) |
||
488 | * array[0] = get_lang('NoCategory');. |
||
489 | * |
||
490 | * @param int $courseId |
||
491 | * |
||
492 | * @return array |
||
493 | */ |
||
494 | public static function getCategoriesIdAndName($courseId = 0) |
||
495 | { |
||
496 | if (empty($courseId)) { |
||
497 | $courseId = api_get_course_int_id(); |
||
498 | } |
||
499 | $categories = self::getCategoryListInfo('', $courseId); |
||
500 | $result = ['0' => get_lang('NoCategorySelected')]; |
||
501 | for ($i = 0; $i < count($categories); $i++) { |
||
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
|
|||
502 | $result[$categories[$i]->iid] = Security::remove_XSS($categories[$i]->name); |
||
503 | } |
||
504 | |||
505 | return $result; |
||
506 | } |
||
507 | |||
508 | /** |
||
509 | * Returns an array of question ids for each category |
||
510 | * $categories[1][30] = 10, array with category id = 1 and question_id = 10 |
||
511 | * A question has "n" categories. |
||
512 | * |
||
513 | * @param int $exerciseId |
||
514 | * @param array $check_in_question_list |
||
515 | * @param array $categoriesAddedInExercise |
||
516 | * |
||
517 | * @return array |
||
518 | */ |
||
519 | public static function getQuestionsByCat( |
||
520 | $exerciseId, |
||
521 | $check_in_question_list = [], |
||
522 | $categoriesAddedInExercise = [], |
||
523 | $onlyMandatory = false |
||
524 | ) { |
||
525 | $tableQuestion = Database::get_course_table(TABLE_QUIZ_QUESTION); |
||
526 | $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION); |
||
527 | $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); |
||
528 | $categoryTable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
529 | $exerciseId = (int) $exerciseId; |
||
530 | $courseId = api_get_course_int_id(); |
||
531 | |||
532 | $mandatoryCondition = ''; |
||
533 | if ($onlyMandatory) { |
||
534 | $mandatoryCondition = ' AND qrc.mandatory = 1'; |
||
535 | } |
||
536 | |||
537 | $sql = "SELECT DISTINCT qrc.question_id, qrc.category_id |
||
538 | FROM $TBL_QUESTION_REL_CATEGORY qrc |
||
539 | INNER JOIN $TBL_EXERCICE_QUESTION eq |
||
540 | ON (eq.question_id = qrc.question_id) |
||
541 | INNER JOIN $categoryTable c |
||
542 | ON (c.iid = qrc.category_id AND c.c_id = eq.c_id) |
||
543 | INNER JOIN $tableQuestion q |
||
544 | ON q.iid = qrc.question_id |
||
545 | WHERE |
||
546 | exercice_id = $exerciseId AND |
||
547 | qrc.c_id = $courseId |
||
548 | $mandatoryCondition |
||
549 | "; |
||
550 | |||
551 | $res = Database::query($sql); |
||
552 | $categories = []; |
||
553 | while ($data = Database::fetch_array($res)) { |
||
554 | if (!empty($check_in_question_list)) { |
||
555 | if (!in_array($data['question_id'], $check_in_question_list)) { |
||
556 | continue; |
||
557 | } |
||
558 | } |
||
559 | |||
560 | if (!isset($categories[$data['category_id']]) || |
||
561 | !is_array($categories[$data['category_id']]) |
||
562 | ) { |
||
563 | $categories[$data['category_id']] = []; |
||
564 | } |
||
565 | |||
566 | $categories[$data['category_id']][] = $data['question_id']; |
||
567 | } |
||
568 | |||
569 | if (!empty($categoriesAddedInExercise)) { |
||
570 | $newCategoryList = []; |
||
571 | foreach ($categoriesAddedInExercise as $category) { |
||
572 | $categoryId = $category['category_id']; |
||
573 | if (isset($categories[$categoryId])) { |
||
574 | $newCategoryList[$categoryId] = $categories[$categoryId]; |
||
575 | } |
||
576 | } |
||
577 | |||
578 | $checkQuestionsWithNoCategory = false; |
||
579 | foreach ($categoriesAddedInExercise as $category) { |
||
580 | if (empty($category['category_id'])) { |
||
581 | // Check |
||
582 | $checkQuestionsWithNoCategory = true; |
||
583 | break; |
||
584 | } |
||
585 | } |
||
586 | |||
587 | // Select questions that don't have any category related |
||
588 | if ($checkQuestionsWithNoCategory) { |
||
589 | $originalQuestionList = $check_in_question_list; |
||
590 | foreach ($originalQuestionList as $questionId) { |
||
591 | $categoriesFlatten = array_flatten($categories); |
||
592 | if (!in_array($questionId, $categoriesFlatten)) { |
||
593 | $newCategoryList[0][] = $questionId; |
||
594 | } |
||
595 | } |
||
596 | } |
||
597 | $categories = $newCategoryList; |
||
598 | } |
||
599 | |||
600 | return $categories; |
||
601 | } |
||
602 | |||
603 | /** |
||
604 | * Returns an array of $numberElements from $elements. |
||
605 | * |
||
606 | * @param array $elements |
||
607 | * @param int $numberElements |
||
608 | * @param bool $shuffle |
||
609 | * @param array $mandatoryElements |
||
610 | * |
||
611 | * @return array |
||
612 | */ |
||
613 | public static function getNElementsFromArray($elements, $numberElements, $shuffle = true, $mandatoryElements = []) |
||
614 | { |
||
615 | $countElements = count($elements); |
||
616 | $countMandatory = count($mandatoryElements); |
||
617 | |||
618 | if (!empty($countMandatory)) { |
||
619 | if ($countMandatory >= $numberElements) { |
||
620 | if ($shuffle) { |
||
621 | shuffle($mandatoryElements); |
||
622 | } |
||
623 | $elements = array_slice($mandatoryElements, 0, $numberElements); |
||
624 | |||
625 | return $elements; |
||
626 | } |
||
627 | |||
628 | $diffCount = $numberElements - $countMandatory; |
||
629 | $diffElements = array_diff($elements, $mandatoryElements); |
||
630 | if ($shuffle) { |
||
631 | shuffle($diffElements); |
||
632 | } |
||
633 | $elements = array_slice($diffElements, 0, $diffCount); |
||
634 | $totalElements = array_merge($mandatoryElements, $elements); |
||
635 | if ($shuffle) { |
||
636 | shuffle($totalElements); |
||
637 | } |
||
638 | |||
639 | return $totalElements; |
||
640 | } |
||
641 | |||
642 | if ($shuffle) { |
||
643 | shuffle($elements); |
||
644 | } |
||
645 | |||
646 | if ($numberElements < $countElements) { |
||
647 | $elements = array_slice($elements, 0, $numberElements); |
||
648 | } |
||
649 | |||
650 | return $elements; |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * @param int $questionId |
||
655 | * @param int $displayCategoryName |
||
656 | */ |
||
657 | public static function displayCategoryAndTitle($questionId, $displayCategoryName = 1) |
||
658 | { |
||
659 | echo self::returnCategoryAndTitle($questionId, $displayCategoryName); |
||
660 | } |
||
661 | |||
662 | /** |
||
663 | * @param int $questionId |
||
664 | * @param int $in_display_category_name |
||
665 | * |
||
666 | * @return string|null |
||
667 | */ |
||
668 | public static function returnCategoryAndTitle($questionId, $in_display_category_name = 1) |
||
669 | { |
||
670 | $is_student = !(api_is_allowed_to_edit(null, true) || api_is_session_admin()); |
||
671 | $objExercise = Session::read('objExercise'); |
||
672 | if (!empty($objExercise)) { |
||
673 | $in_display_category_name = $objExercise->display_category_name; |
||
674 | } |
||
675 | $content = null; |
||
676 | if (self::getCategoryNameForQuestion($questionId) != '' && |
||
677 | ($in_display_category_name == 1 || !$is_student) |
||
678 | ) { |
||
679 | $content .= '<div class="page-header">'; |
||
680 | $content .= '<h4>'.get_lang('Category').": ".Security::remove_XSS(self::getCategoryNameForQuestion($questionId)).'</h4>'; |
||
681 | $content .= "</div>"; |
||
682 | } |
||
683 | |||
684 | return $content; |
||
685 | } |
||
686 | |||
687 | /** |
||
688 | * sortTabByBracketLabel ($tabCategoryQuestions) |
||
689 | * key of $tabCategoryQuestions are the category id (0 for not in a category) |
||
690 | * value is the array of question id of this category |
||
691 | * Sort question by Category. |
||
692 | */ |
||
693 | public static function sortTabByBracketLabel($in_tab) |
||
694 | { |
||
695 | $tabResult = []; |
||
696 | $tabCatName = []; // tab of category name |
||
697 | foreach ($in_tab as $cat_id => $tabquestion) { |
||
698 | $category = new TestCategory(); |
||
699 | $category = $category->getCategory($cat_id); |
||
700 | $tabCatName[$cat_id] = $category->name; |
||
701 | } |
||
702 | reset($in_tab); |
||
703 | // sort table by value, keeping keys as they are |
||
704 | asort($tabCatName); |
||
705 | // keys of $tabCatName are keys order for $in_tab |
||
706 | foreach ($tabCatName as $key => $val) { |
||
707 | $tabResult[$key] = $in_tab[$key]; |
||
708 | } |
||
709 | |||
710 | return $tabResult; |
||
711 | } |
||
712 | |||
713 | /** |
||
714 | * Return the number max of question in a category |
||
715 | * count the number of questions in all categories, and return the max. |
||
716 | * |
||
717 | * @param int $exerciseId |
||
718 | * |
||
719 | * @author - hubert borderiou |
||
720 | * |
||
721 | * @return int |
||
722 | */ |
||
723 | public static function getNumberMaxQuestionByCat($exerciseId) |
||
724 | { |
||
725 | $res_num_max = 0; |
||
726 | // foreach question |
||
727 | $categories = self::getListOfCategoriesIDForTest($exerciseId); |
||
728 | foreach ($categories as $category) { |
||
729 | if (empty($category['iid'])) { |
||
730 | continue; |
||
731 | } |
||
732 | |||
733 | $nbQuestionInThisCat = self::getNumberOfQuestionsInCategoryForTest( |
||
734 | $exerciseId, |
||
735 | $category['iid'] |
||
736 | ); |
||
737 | |||
738 | if ($nbQuestionInThisCat > $res_num_max) { |
||
739 | $res_num_max = $nbQuestionInThisCat; |
||
740 | } |
||
741 | } |
||
742 | |||
743 | return $res_num_max; |
||
744 | } |
||
745 | |||
746 | /** |
||
747 | * Returns a category summary report. |
||
748 | * |
||
749 | * @param Exercise $exercise |
||
750 | * @param array $category_list |
||
751 | * pre filled array with the category_id, score, and weight |
||
752 | * example: array(1 => array('score' => '10', 'total' => 20)); |
||
753 | * |
||
754 | * @return string |
||
755 | */ |
||
756 | public static function get_stats_table_by_attempt($exercise, $category_list = []) |
||
757 | { |
||
758 | if (empty($category_list) || empty($exercise)) { |
||
759 | return ''; |
||
760 | } |
||
761 | |||
762 | $hide = (int) $exercise->getPageConfigurationAttribute('hide_category_table'); |
||
763 | if (1 === $hide) { |
||
764 | return ''; |
||
765 | } |
||
766 | |||
767 | $exerciseId = $exercise->iid; |
||
768 | $categoryNameList = self::getListOfCategoriesNameForTest($exerciseId); |
||
769 | |||
770 | $table = new HTML_Table( |
||
771 | [ |
||
772 | 'class' => 'table table-hover table-striped table-bordered', |
||
773 | 'id' => 'category_results', |
||
774 | ] |
||
775 | ); |
||
776 | $table->setHeaderContents(0, 0, get_lang('Categories')); |
||
777 | $table->setHeaderContents(0, 1, get_lang('AbsoluteScore')); |
||
778 | $table->setHeaderContents(0, 2, get_lang('RelativeScore')); |
||
779 | $row = 1; |
||
780 | |||
781 | $none_category = []; |
||
782 | if (isset($category_list['none'])) { |
||
783 | $none_category = $category_list['none']; |
||
784 | unset($category_list['none']); |
||
785 | } |
||
786 | |||
787 | $total = []; |
||
788 | if (isset($category_list['total'])) { |
||
789 | $total = $category_list['total']; |
||
790 | unset($category_list['total']); |
||
791 | } |
||
792 | |||
793 | $radar = ''; |
||
794 | $countCategories = count($category_list); |
||
795 | if ($countCategories > 1) { |
||
796 | $tempResult = []; |
||
797 | $labels = []; |
||
798 | $labelsWithId = array_column($categoryNameList, 'title', 'iid'); |
||
799 | asort($labelsWithId); |
||
800 | foreach ($labelsWithId as $category_id => $title) { |
||
801 | if (!isset($category_list[$category_id])) { |
||
802 | continue; |
||
803 | } |
||
804 | $labels[] = $title; |
||
805 | $category_item = $category_list[$category_id]; |
||
806 | |||
807 | $table->setCellContents($row, 0, $title); |
||
808 | $table->setCellContents( |
||
809 | $row, |
||
810 | 1, |
||
811 | ExerciseLib::show_score( |
||
812 | $category_item['score'], |
||
813 | $category_item['total'], |
||
814 | false |
||
815 | ) |
||
816 | ); |
||
817 | $table->setCellContents( |
||
818 | $row, |
||
819 | 2, |
||
820 | ExerciseLib::show_score( |
||
821 | $category_item['score'], |
||
822 | $category_item['total'], |
||
823 | true, |
||
824 | false, |
||
825 | true |
||
826 | ) |
||
827 | ); |
||
828 | $tempResult[$category_id] = round($category_item['score'] / $category_item['total'] * 10); |
||
829 | $row++; |
||
830 | } |
||
831 | |||
832 | // Radar requires more than 3 categories. |
||
833 | if ($countCategories > 2 && RESULT_DISABLE_RADAR === (int) $exercise->results_disabled) { |
||
834 | $resultsArray = []; |
||
835 | foreach ($labelsWithId as $categoryId => $label) { |
||
836 | if (isset($tempResult[$categoryId])) { |
||
837 | $resultsArray[] = $tempResult[$categoryId]; |
||
838 | } else { |
||
839 | $resultsArray[] = 0; |
||
840 | } |
||
841 | } |
||
842 | $radar = $exercise->getRadar($labels, [$resultsArray]); |
||
843 | } |
||
844 | |||
845 | if (!empty($none_category)) { |
||
846 | $table->setCellContents($row, 0, get_lang('None')); |
||
847 | $table->setCellContents( |
||
848 | $row, |
||
849 | 1, |
||
850 | ExerciseLib::show_score( |
||
851 | $none_category['score'], |
||
852 | $none_category['total'], |
||
853 | false |
||
854 | ) |
||
855 | ); |
||
856 | $table->setCellContents( |
||
857 | $row, |
||
858 | 2, |
||
859 | ExerciseLib::show_score( |
||
860 | $none_category['score'], |
||
861 | $none_category['total'], |
||
862 | true, |
||
863 | false, |
||
864 | true |
||
865 | ) |
||
866 | ); |
||
867 | $row++; |
||
868 | } |
||
869 | if (!empty($total)) { |
||
870 | $table->setCellContents($row, 0, get_lang('Total')); |
||
871 | $table->setCellContents( |
||
872 | $row, |
||
873 | 1, |
||
874 | ExerciseLib::show_score( |
||
875 | $total['score'], |
||
876 | $total['total'], |
||
877 | false |
||
878 | ) |
||
879 | ); |
||
880 | $table->setCellContents( |
||
881 | $row, |
||
882 | 2, |
||
883 | ExerciseLib::show_score( |
||
884 | $total['score'], |
||
885 | $total['total'], |
||
886 | true, |
||
887 | false, |
||
888 | true |
||
889 | ) |
||
890 | ); |
||
891 | } |
||
892 | |||
893 | return $radar.$table->toHtml(); |
||
894 | } |
||
895 | |||
896 | return ''; |
||
897 | } |
||
898 | |||
899 | /** |
||
900 | * @param Exercise $exercise |
||
901 | * @param int $courseId |
||
902 | * @param string $order |
||
903 | * @param bool $shuffle |
||
904 | * @param bool $excludeCategoryWithNoQuestions |
||
905 | * |
||
906 | * @return array |
||
907 | */ |
||
908 | public function getCategoryExerciseTree( |
||
909 | $exercise, |
||
910 | $courseId, |
||
911 | $order = null, |
||
912 | $shuffle = false, |
||
913 | $excludeCategoryWithNoQuestions = true |
||
914 | ) { |
||
915 | if (empty($exercise)) { |
||
916 | return []; |
||
917 | } |
||
918 | |||
919 | $courseId = (int) $courseId; |
||
920 | $table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY); |
||
921 | $categoryTable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
922 | $exercise->iid = (int) $exercise->iid; |
||
923 | |||
924 | $sql = "SELECT * FROM $table qc |
||
925 | LEFT JOIN $categoryTable c |
||
926 | ON (c.iid = qc.category_id) |
||
927 | WHERE qc.c_id = $courseId AND exercise_id = {$exercise->iid} "; |
||
928 | |||
929 | if (!empty($order)) { |
||
930 | $order = Database::escape_string($order); |
||
931 | $sql .= "ORDER BY $order"; |
||
932 | } |
||
933 | |||
934 | $categories = []; |
||
935 | $result = Database::query($sql); |
||
936 | if (Database::num_rows($result)) { |
||
937 | while ($row = Database::fetch_array($result, 'ASSOC')) { |
||
938 | if ($excludeCategoryWithNoQuestions) { |
||
939 | if ($row['count_questions'] == 0) { |
||
940 | continue; |
||
941 | } |
||
942 | } |
||
943 | if (empty($row['title']) && empty($row['category_id'])) { |
||
944 | $row['title'] = get_lang('NoCategory'); |
||
945 | } |
||
946 | $categories[$row['category_id']] = $row; |
||
947 | } |
||
948 | } |
||
949 | |||
950 | if ($shuffle) { |
||
951 | shuffle_assoc($categories); |
||
952 | } |
||
953 | |||
954 | return $categories; |
||
955 | } |
||
956 | |||
957 | /** |
||
958 | * @param FormValidator $form |
||
959 | * @param string $action |
||
960 | */ |
||
961 | public function getForm(&$form, $action = 'new') |
||
962 | { |
||
963 | switch ($action) { |
||
964 | case 'new': |
||
965 | $header = get_lang('AddACategory'); |
||
966 | $submit = get_lang('AddTestCategory'); |
||
967 | break; |
||
968 | case 'edit': |
||
969 | $header = get_lang('EditCategory'); |
||
970 | $submit = get_lang('ModifyCategory'); |
||
971 | break; |
||
972 | } |
||
973 | |||
974 | // Setting the form elements |
||
975 | $form->addElement('header', $header); |
||
976 | $form->addElement('hidden', 'category_id'); |
||
977 | $form->addElement( |
||
978 | 'text', |
||
979 | 'category_name', |
||
980 | get_lang('CategoryName'), |
||
981 | ['class' => 'span6'] |
||
982 | ); |
||
983 | $form->add_html_editor( |
||
984 | 'category_description', |
||
985 | get_lang('CategoryDescription'), |
||
986 | false, |
||
987 | false, |
||
988 | [ |
||
989 | 'ToolbarSet' => 'test_category', |
||
990 | 'Width' => '90%', |
||
991 | 'Height' => '200', |
||
992 | ] |
||
993 | ); |
||
994 | $category_parent_list = []; |
||
995 | |||
996 | $options = [ |
||
997 | '1' => get_lang('Visible'), |
||
998 | '0' => get_lang('Hidden'), |
||
999 | ]; |
||
1000 | $form->addElement( |
||
1001 | 'select', |
||
1002 | 'visibility', |
||
1003 | get_lang('Visibility'), |
||
1004 | $options |
||
1005 | ); |
||
1006 | $script = null; |
||
1007 | if (!empty($this->parent_id)) { |
||
1008 | $parent_cat = new TestCategory(); |
||
1009 | $parent_cat = $parent_cat->getCategory($this->parent_id); |
||
1010 | $category_parent_list = [$parent_cat->iid => $parent_cat->name]; |
||
1011 | $script .= '<script>$(function() { $("#parent_id").trigger("addItem",[{"title": "'.$parent_cat->name.'", "value": "'.$parent_cat->iid.'"}]); });</script>'; |
||
1012 | } |
||
1013 | $form->addElement('html', $script); |
||
1014 | |||
1015 | $form->addElement('select', 'parent_id', get_lang('Parent'), $category_parent_list, ['id' => 'parent_id']); |
||
1016 | $form->addElement('style_submit_button', 'SubmitNote', $submit, 'class="add"'); |
||
1017 | |||
1018 | // setting the defaults |
||
1019 | $defaults = []; |
||
1020 | $defaults["category_id"] = $this->iid; |
||
1021 | $defaults["category_name"] = $this->name; |
||
1022 | $defaults["category_description"] = $this->description; |
||
1023 | $defaults["parent_id"] = $this->parent_id; |
||
1024 | $defaults["visibility"] = $this->visibility; |
||
1025 | $form->setDefaults($defaults); |
||
1026 | |||
1027 | // setting the rules |
||
1028 | $form->addRule('category_name', get_lang('ThisFieldIsRequired'), 'required'); |
||
1029 | } |
||
1030 | |||
1031 | /** |
||
1032 | * Returns the category form. |
||
1033 | * |
||
1034 | * @return string |
||
1035 | */ |
||
1036 | public function returnCategoryForm(Exercise $exercise) |
||
1037 | { |
||
1038 | $categories = $this->getListOfCategoriesForTest($exercise); |
||
1039 | $sortedCategories = []; |
||
1040 | foreach ($categories as $catId => $cat) { |
||
1041 | $sortedCategories[$cat['title']] = $cat; |
||
1042 | } |
||
1043 | ksort($sortedCategories); |
||
1044 | $saved_categories = $exercise->getCategoriesInExercise(); |
||
1045 | $return = null; |
||
1046 | |||
1047 | if (!empty($sortedCategories)) { |
||
1048 | $nbQuestionsTotal = $exercise->getNumberQuestionExerciseCategory(); |
||
1049 | $exercise->setCategoriesGrouping(true); |
||
1050 | $real_question_count = count($exercise->getQuestionList()); |
||
1051 | |||
1052 | $warning = null; |
||
1053 | if ($nbQuestionsTotal != $real_question_count) { |
||
1054 | $warning = Display::return_message( |
||
1055 | get_lang('CheckThatYouHaveEnoughQuestionsInYourCategories'), |
||
1056 | 'warning' |
||
1057 | ); |
||
1058 | } |
||
1059 | |||
1060 | $return .= $warning; |
||
1061 | $return .= '<table class="table table-hover table-bordered data_table">'; |
||
1062 | $return .= '<tr>'; |
||
1063 | $return .= '<th height="24">'.get_lang('Categories').'</th>'; |
||
1064 | $return .= '<th width="70" height="24">'.get_lang('Number').'</th></tr>'; |
||
1065 | |||
1066 | $emptyCategory = [ |
||
1067 | 'id' => '0', |
||
1068 | 'name' => get_lang('NoCategory'), |
||
1069 | 'description' => '', |
||
1070 | 'iid' => '0', |
||
1071 | 'title' => get_lang('NoCategory'), |
||
1072 | ]; |
||
1073 | |||
1074 | $sortedCategories[] = $emptyCategory; |
||
1075 | |||
1076 | foreach ($sortedCategories as $category) { |
||
1077 | $cat_id = $category['iid']; |
||
1078 | $return .= '<tr>'; |
||
1079 | $return .= '<td>'; |
||
1080 | $return .= Display::div($category['name']); |
||
1081 | $return .= '</td>'; |
||
1082 | $return .= '<td>'; |
||
1083 | $value = isset($saved_categories) && isset($saved_categories[$cat_id]) ? $saved_categories[$cat_id]['count_questions'] : -1; |
||
1084 | $return .= Display::input( |
||
1085 | 'number', |
||
1086 | "category[$cat_id]", |
||
1087 | $value, |
||
1088 | ['class' => 'form-control', 'min' => -1, 'step' => 1] |
||
1089 | ); |
||
1090 | $return .= '</td>'; |
||
1091 | $return .= '</tr>'; |
||
1092 | } |
||
1093 | |||
1094 | $return .= '</table>'; |
||
1095 | $return .= get_lang('ZeroMeansNoQuestionWillBeSelectedMinusOneMeansThatAllQuestionsWillBeSelected'); |
||
1096 | } |
||
1097 | |||
1098 | return $return; |
||
1099 | } |
||
1100 | |||
1101 | /** |
||
1102 | * Return true if a category already exists with the same name. |
||
1103 | * |
||
1104 | * @param string $name |
||
1105 | * @param int $courseId |
||
1106 | * |
||
1107 | * @return bool |
||
1108 | */ |
||
1109 | public static function categoryTitleExists($name, $courseId = 0) |
||
1110 | { |
||
1111 | $categories = self::getCategoryListInfo('title', $courseId); |
||
1112 | foreach ($categories as $title) { |
||
1113 | if ($title == $name) { |
||
1114 | return true; |
||
1115 | } |
||
1116 | } |
||
1117 | |||
1118 | return false; |
||
1119 | } |
||
1120 | |||
1121 | /** |
||
1122 | * Return the id of the test category with title = $in_title. |
||
1123 | * |
||
1124 | * @param string $title |
||
1125 | * @param int $courseId |
||
1126 | * |
||
1127 | * @return int is id of test category |
||
1128 | */ |
||
1129 | public static function get_category_id_for_title($title, $courseId = 0) |
||
1130 | { |
||
1131 | $out_res = 0; |
||
1132 | if (empty($courseId)) { |
||
1133 | $courseId = api_get_course_int_id(); |
||
1134 | } |
||
1135 | $courseId = (int) $courseId; |
||
1136 | $tbl_cat = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
1137 | $sql = "SELECT iid FROM $tbl_cat |
||
1138 | WHERE c_id = $courseId AND title = '".Database::escape_string($title)."'"; |
||
1139 | $res = Database::query($sql); |
||
1140 | if (Database::num_rows($res) > 0) { |
||
1141 | $data = Database::fetch_array($res); |
||
1142 | $out_res = $data['iid']; |
||
1143 | } |
||
1144 | |||
1145 | return $out_res; |
||
1146 | } |
||
1147 | |||
1148 | /** |
||
1149 | * Add a relation between question and category in table c_quiz_question_rel_category. |
||
1150 | * |
||
1151 | * @param int $categoryId |
||
1152 | * @param int $questionId |
||
1153 | * @param int $courseId |
||
1154 | * |
||
1155 | * @return string|false |
||
1156 | */ |
||
1157 | public static function addCategoryToQuestion($categoryId, $questionId, $courseId) |
||
1158 | { |
||
1159 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY); |
||
1160 | // if question doesn't have a category |
||
1161 | // @todo change for 1.10 when a question can have several categories |
||
1162 | if (self::getCategoryForQuestion($questionId, $courseId) == 0 && |
||
1163 | $questionId > 0 && |
||
1164 | $courseId > 0 |
||
1165 | ) { |
||
1166 | $sql = "INSERT INTO $table (c_id, question_id, category_id) |
||
1167 | VALUES (".intval($courseId).", ".intval($questionId).", ".intval($categoryId).")"; |
||
1168 | Database::query($sql); |
||
1169 | $id = Database::insert_id(); |
||
1170 | |||
1171 | return $id; |
||
1172 | } |
||
1173 | |||
1174 | return false; |
||
1175 | } |
||
1176 | |||
1177 | /** |
||
1178 | * @param int $courseId |
||
1179 | * @param int $sessionId |
||
1180 | * |
||
1181 | * @return array |
||
1182 | */ |
||
1183 | public function getCategories($courseId, $sessionId = 0) |
||
1184 | { |
||
1185 | $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY); |
||
1186 | $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY); |
||
1187 | $sessionId = intval($sessionId); |
||
1188 | $courseId = intval($courseId); |
||
1189 | |||
1190 | if (empty($sessionId)) { |
||
1191 | $sessionCondition = api_get_session_condition( |
||
1192 | $sessionId, |
||
1193 | true, |
||
1194 | false, |
||
1195 | 'i.session_id' |
||
1196 | ); |
||
1197 | } else { |
||
1198 | $sessionCondition = api_get_session_condition( |
||
1199 | $sessionId, |
||
1200 | true, |
||
1201 | true, |
||
1202 | 'i.session_id' |
||
1203 | ); |
||
1204 | } |
||
1205 | |||
1206 | if (empty($courseId)) { |
||
1207 | return []; |
||
1208 | } |
||
1209 | |||
1210 | $sql = "SELECT cat.* FROM $table cat |
||
1211 | INNER JOIN $itemProperty i |
||
1212 | ON cat.c_id = i.c_id AND i.ref = cat.iid |
||
1213 | WHERE |
||
1214 | cat.c_id = $courseId AND |
||
1215 | i.tool = '".TOOL_TEST_CATEGORY."' |
||
1216 | $sessionCondition |
||
1217 | ORDER BY title ASC"; |
||
1218 | $result = Database::query($sql); |
||
1219 | |||
1220 | return Database::store_result($result, 'ASSOC'); |
||
1221 | } |
||
1222 | |||
1223 | /** |
||
1224 | * @param int $courseId |
||
1225 | * @param int $sessionId |
||
1226 | * |
||
1227 | * @return string |
||
1228 | */ |
||
1229 | public function displayCategories($courseId, $sessionId = 0) |
||
1230 | { |
||
1231 | $sessionId = (int) $sessionId; |
||
1232 | $categories = $this->getCategories($courseId, $sessionId); |
||
1233 | $html = ''; |
||
1234 | foreach ($categories as $category) { |
||
1235 | $tmpobj = new TestCategory(); |
||
1236 | $tmpobj = $tmpobj->getCategory($category['iid']); |
||
1237 | $nb_question = $tmpobj->getCategoryQuestionsNumber(); |
||
1238 | $rowname = self::protectJSDialogQuote($category['title']); |
||
1239 | $nb_question_label = $nb_question == 1 ? $nb_question.' '.get_lang('Question') : $nb_question.' '.get_lang('Questions'); |
||
1240 | $content = "<span style='float:right'>".$nb_question_label."</span>"; |
||
1241 | $content .= '<div class="sectioncomment">'; |
||
1242 | $content .= Security::remove_XSS($category['description']); |
||
1243 | $content .= '</div>'; |
||
1244 | $links = ''; |
||
1245 | |||
1246 | if (!$sessionId) { |
||
1247 | $links .= '<a href="'.api_get_self().'?action=editcategory&category_id='.$category['iid'].'&'.api_get_cidreq().'">'. |
||
1248 | Display::return_icon('edit.png', get_lang('Edit'), [], ICON_SIZE_SMALL).'</a>'; |
||
1249 | $links .= ' <a href="'.api_get_self().'?'.api_get_cidreq().'&action=deletecategory&category_id='.$category['iid'].'" '; |
||
1250 | $links .= 'onclick="return confirmDelete(\''.self::protectJSDialogQuote(get_lang('DeleteCategoryAreYouSure').'['.$rowname).'] ?\', \'id_cat'.$category['iid'].'\');">'; |
||
1251 | $links .= Display::return_icon('delete.png', get_lang('Delete'), [], ICON_SIZE_SMALL).'</a>'; |
||
1252 | } |
||
1253 | |||
1254 | $html .= Display::panel($content, Security::remove_XSS($category['title']).$links); |
||
1255 | } |
||
1256 | |||
1257 | return $html; |
||
1258 | } |
||
1259 | |||
1260 | /** |
||
1261 | * To allowed " in javascript dialog box without bad surprises |
||
1262 | * replace " with two '. |
||
1263 | * |
||
1264 | * @param string $text |
||
1265 | * |
||
1266 | * @return mixed |
||
1267 | */ |
||
1268 | public function protectJSDialogQuote($text) |
||
1269 | { |
||
1270 | $res = $text; |
||
1271 | $res = str_replace("'", "\'", $res); |
||
1272 | // super astuce pour afficher les " dans les boite de dialogue |
||
1273 | $res = str_replace('"', "\'\'", $res); |
||
1274 | |||
1275 | return $res; |
||
1276 | } |
||
1277 | } |
||
1278 |
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: