Completed
Push — 1.10.x ( c11148...3f49cd )
by Angel Fernando Quiroz
162:29 queued 117:01
created

getNumberOfQuestionRandomByCategory()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 4
eloc 12
c 1
b 1
f 0
nc 4
nop 2
dl 0
loc 21
rs 9.0534
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Class TestCategory
6
 * @author hubert.borderiou
7
 * @author Julio Montoya - several fixes
8
 * @todo rename to ExerciseCategory
9
 */
10
class TestCategory
11
{
12
    public $id;
13
    public $name;
14
    public $description;
15
16
	/**
17
	 * Constructor of the class Category
18
	 * If you give an in_id and no in_name, you get info concerning the category of id=in_id
19
	 * otherwise, you've got an category objet avec your in_id, in_name, in_descr
20
	 *
21
     * @param int    $id
22
     * @param string $name
23
     * @param string $description
24
     *
25
     * @author - Hubert Borderiou
26
     */
27
    public function __construct($id = 0, $name = '', $description = "")
28
    {
29
        if ($id != 0 && $name == "") {
30
            $obj = new TestCategory();
31
            $obj->getCategory($id);
32
            $this->id = $obj->id;
33
            $this->name = $obj->name;
34
            $this->description = $obj->description;
35
        } else {
36
            $this->id = $id;
37
            $this->name = $name;
38
            $this->description = $description;
39
        }
40
    }
41
42
    /**
43
     * return the TestCategory object with id=in_id
44
     * @param int $id
45
     *
46
     * @return TestCategory
47
     */
48
    public function getCategory($id)
49
    {
50
        $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
51
        $id = intval($id);
52
        $sql = "SELECT * FROM $table
53
                WHERE id = $id AND c_id=".api_get_course_int_id();
54
        $res = Database::query($sql);
55
56
        if (Database::num_rows($res)) {
57
            $row = Database::fetch_array($res);
58
            $this->id = $row['id'];
59
            $this->name = $row['title'];
60
            $this->description  = $row['description'];
61
        }
62
    }
63
64
	/**
65
     * add TestCategory in the database if name doesn't already exists
66
	 */
67
    public function addCategoryInBDD()
68
    {
69
        $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
70
        $v_name = $this->name;
71
        $v_name = Database::escape_string($v_name);
72
        $v_description = $this->description;
73
        $v_description = Database::escape_string($v_description);
74
        // check if name already exists
75
        $sql = "SELECT count(*) AS nb FROM $table
76
                WHERE title = '$v_name' AND c_id=".api_get_course_int_id();
77
        $result_verif = Database::query($sql);
78
        $data_verif = Database::fetch_array($result_verif);
79
        // lets add in BDD if not the same name
80
        if ($data_verif['nb'] <= 0) {
81
            $c_id = api_get_course_int_id();
82
            $params = [
83
                'c_id' => $c_id,
84
                'title' => $v_name,
85
                'description' => $v_description,
86
            ];
87
            $new_id = Database::insert($table, $params);
88
89
            if ($new_id) {
90
91
                $sql = "UPDATE $table SET id = iid WHERE iid = $new_id";
92
                Database::query($sql);
93
94
                // add test_category in item_property table
95
                $course_id = api_get_course_int_id();
96
                $course_info = api_get_course_info_by_id($course_id);
97
                api_item_property_update(
98
                    $course_info,
99
                    TOOL_TEST_CATEGORY,
100
                    $new_id,
101
                    'TestCategoryAdded',
102
                    api_get_user_id()
103
                );
104
            }
105
106
            return $new_id;
107
        } else {
108
109
            return false;
110
        }
111
	}
112
113
	/**
114
     * Removes the category from the database
115
     * if there were question in this category, the link between question and category is removed
116
	 */
117
    public function removeCategory()
118
    {
119
        $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
120
        $tbl_question_rel_cat = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
121
        $v_id = intval($this->id);
122
        $course_id = api_get_course_int_id();
123
124
        $sql = "DELETE FROM $table
125
                WHERE id= $v_id AND c_id=".$course_id;
126
        $result = Database::query($sql);
127
        if (Database::affected_rows($result) <= 0) {
128
            return false;
129
        } else {
130
            // remove link between question and category
131
            $sql2 = "DELETE FROM $tbl_question_rel_cat
132
                     WHERE category_id = $v_id AND c_id=".$course_id;
133
            Database::query($sql2);
134
            // item_property update
135
            $course_info = api_get_course_info_by_id($course_id);
136
            api_item_property_update(
137
                $course_info,
138
                TOOL_TEST_CATEGORY,
139
                $this->id,
140
                'TestCategoryDeleted',
141
                api_get_user_id()
142
            );
143
144
            return true;
145
        }
146
	}
147
148
	/**
149
     * Modify category name or description of category with id=in_id
150
	 */
151
    public function modifyCategory()
152
    {
153
        $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
154
        $v_id = intval($this->id);
155
        $v_name = Database::escape_string($this->name);
156
        $v_description = Database::escape_string($this->description);
157
        $sql = "UPDATE $table SET
158
                title = '$v_name',
159
                description = '$v_description'
160
                WHERE id = $v_id AND c_id=".api_get_course_int_id();
161
        $result = Database::query($sql);
162
        if (Database::affected_rows($result) <= 0) {
163
            return false;
164
        } else {
165
            // item_property update
166
            $course_id = api_get_course_int_id();
167
            $course_info = api_get_course_info_by_id($course_id);
168
            api_item_property_update(
169
                $course_info,
170
                TOOL_TEST_CATEGORY,
171
                $this->id,
172
                'TestCategoryModified',
173
                api_get_user_id()
174
            );
175
176
            return true;
177
        }
178
	}
179
180
	/**
181
     * Gets the number of question of category id=in_id
182
	 */
183
    public function getCategoryQuestionsNumber()
184
    {
185
		$table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
186
		$in_id = intval($this->id);
187
		$sql = "SELECT count(*) AS nb
188
		        FROM $table
189
		        WHERE category_id=$in_id AND c_id=".api_get_course_int_id();
190
		$res = Database::query($sql);
191
		$row = Database::fetch_array($res);
192
193
		return $row['nb'];
194
	}
195
196
    /**
197
     * @param string $in_color
198
     */
199
    public function display($in_color="#E0EBF5")
200
    {
201
		echo "<textarea style='background-color:$in_color; width:60%; height:100px;'>";
202
		print_r($this);
203
		echo "</textarea>";
204
	}
205
206
	/**
207
     * Return an array of all Category objects in the database
208
	 * If in_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
    public static function getCategoryListInfo($in_field = "", $courseId = "")
213
    {
214
        if (empty($courseId) || $courseId=="") {
215
            $courseId = api_get_course_int_id();
216
        }
217
        $table = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
218
        $in_field = Database::escape_string($in_field);
219
        $tabres = array();
220
        if ($in_field == "") {
221
            $sql = "SELECT * FROM $table
222
                    WHERE c_id=$courseId ORDER BY title ASC";
223
            $res = Database::query($sql);
224
            while ($row = Database::fetch_array($res)) {
225
                $tmpcat = new TestCategory(
226
                    $row['id'],
227
                    $row['title'],
228
                    $row['description']
229
                );
230
                $tabres[] = $tmpcat;
231
            }
232
        } else {
233
            $sql = "SELECT $in_field FROM $table
234
                    WHERE c_id = $courseId
235
                    ORDER BY $in_field ASC";
236
            $res = Database::query($sql);
237
            while ($row = Database::fetch_array($res)) {
238
                $tabres[] = $row[$in_field];
239
            }
240
        }
241
242
		return $tabres;
243
	}
244
245
    /**
246
     * Return the TestCategory id for question with question_id = $questionId
247
     * In this version, a question has only 1 TestCategory.
248
     * Return the TestCategory id, 0 if none
249
     * @param int $questionId
250
     * @param int $courseId
251
     *
252
     * @return int
253
     */
254 View Code Duplication
	public static function getCategoryForQuestion($questionId, $courseId ="")
255
    {
256
		$result = 0;
257
        if (empty($courseId) || $courseId == "") {
258
            $courseId = api_get_course_int_id();
259
        }
260
		$table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
261
        $questionId = intval($questionId);
262
		$sql = "SELECT category_id
263
		        FROM $table
264
		        WHERE question_id = $questionId AND c_id = $courseId";
265
		$res = Database::query($sql);
266
		if (Database::num_rows($res) > 0) {
267
            $data = Database::fetch_array($res);
268
			$result = $data['category_id'];
269
		}
270
271
		return $result;
272
	}
273
274
	/**
275
	 * true if question id has a category
276
	 */
277
	public static function isQuestionHasCategory($questionId)
278
    {
279
		if (TestCategory::getCategoryForQuestion($questionId) > 0) {
280
			return true;
281
		}
282
		return false;
283
	}
284
285
	/**
286
	 Return the category name for question with question_id = $questionId
287
	 In this version, a question has only 1 category.
288
	 Return the category id, "" if none
289
	 */
290
    public static function getCategoryNameForQuestion(
291
        $questionId,
292
        $courseId = ""
293
    ) {
294
		if (empty($courseId) || $courseId=="") {
295
			$courseId = api_get_course_int_id();
296
		}
297
		$catid = TestCategory::getCategoryForQuestion($questionId, $courseId);
298
		$result = "";	// result
299
		$table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
300
		$catid = intval($catid);
301
		$sql = "SELECT title FROM $table
302
		        WHERE id = $catid  AND c_id = $courseId";
303
		$res = Database::query($sql);
304
		$data = Database::fetch_array($res);
305
		if (Database::num_rows($res) > 0) {
306
			$result = $data['title'];
307
		}
308
309
		return $result;
310
	}
311
312
	/**
313
	 * Return the list of differents categories ID for a test in the current course
314
	 * input : test_id
315
	 * return : array of category id (integer)
316
	 * hubert.borderiou 07-04-2011
317
	 * @param int $exerciseId
318
	 */
319
	public static function getListOfCategoriesIDForTest($exerciseId)
320
    {
321
		// parcourir les questions d'un test, recup les categories uniques dans un tableau
322
		$exercise = new Exercise();
323
		$exercise->read($exerciseId, false);
324
		$categoriesInExercise = $exercise->getQuestionWithCategories();
325
		// the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ???
326
		$categories = array();
327
        if (!empty($categoriesInExercise)) {
328
			foreach ($categoriesInExercise as $category) {
329
				//$category['id'] = $category['iid'];
330
				$categories[$category['id']] = $category;
331
			}
332
		}
333
334
		return $categories;
335
	}
336
337
	/**
338
	 * @param Exercise $exercise_obj
339
	 * @return array
340
	 */
341
	public static function getListOfCategoriesIDForTestObject(Exercise $exercise_obj)
342
	{
343
		// parcourir les questions d'un test, recup les categories uniques dans un tableau
344
		$categories_in_exercise = array();
345
		// $question_list = $exercise_obj->getQuestionList();
346
		$question_list = $exercise_obj->getQuestionOrderedListByName();
347
348
		// the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ???
349
		foreach ($question_list as $questionInfo) {
350
			$question_id = $questionInfo['question_id'];
351
			$category_list = self::getCategoryForQuestion($question_id);
352
			if (is_numeric($category_list)) {
353
				$category_list = array($category_list);
354
			}
355
356
			if (!empty($category_list)) {
357
				$categories_in_exercise = array_merge($categories_in_exercise, $category_list);
358
			}
359
		}
360
		if (!empty($categories_in_exercise)) {
361
			$categories_in_exercise = array_unique(array_filter($categories_in_exercise));
362
		}
363
		return $categories_in_exercise;
364
	}
365
366
	/**
367
	 * Return the list of differents categories NAME for a test
368
	 * @param int exercise id
369
	 * @param bool
370
	 * @return array of string
371
	 *
372
     * @author function rewrote by jmontoya
373
	 */
374
	public static function getListOfCategoriesNameForTest($exercise_id, $grouped_by_category = true)
375
    {
376
		$result = array();
377
		$categories = self::getListOfCategoriesIDForTest($exercise_id, $grouped_by_category);
378
379
		foreach ($categories as $catInfo) {
380
			$categoryId = $catInfo['id'];
381
			if (!empty($categoryId)) {
382
				$result[$categoryId] = array(
383
                    'title' => $catInfo['title'],
384
                    //'parent_id' =>  $catInfo['parent_id'],
385
					'parent_id' => '',
386
                    'c_id' => $catInfo['c_id']
387
                );
388
		}
389
		}
390
391
		return $result;
392
	}
393
394
	/**
395
	 * @param Exercise $exercise_obj
396
	 * @return array
397
	 */
398
	public static function getListOfCategoriesForTest(Exercise $exercise_obj)
399
	{
400
		$result = array();
401
		$categories = self::getListOfCategoriesIDForTestObject($exercise_obj);
402
		foreach ($categories as $cat_id) {
403
			$cat = new TestCategory($cat_id);
404
			$cat = (array)$cat;
405
			$cat['iid'] = $cat['id'];
406
			$cat['title'] = $cat['name'];
407
			$result[$cat['id']] = $cat;
408
		}
409
		return $result;
410
	}
411
412
	/**
413
	 * return the number of differents categories for a test
414
	 * input : test_id
415
	 * return : integer
416
	 * hubert.borderiou 07-04-2011
417
	 */
418
	public static function getNumberOfCategoriesForTest($id)
419
    {
420
		return count(TestCategory::getListOfCategoriesIDForTest($id));
421
	}
422
423
	/**
424
	 * return the number of question of a category id in a test
425
	 * @param int $exerciseId
426
     * @param int $categoryId
427
     *
428
	 * @return integer
429
     *
430
	 * @author hubert.borderiou 07-04-2011
431
	 */
432
	public static function getNumberOfQuestionsInCategoryForTest($exerciseId, $categoryId)
433
    {
434
		$nbCatResult = 0;
435
		$quiz = new Exercise();
436
		$quiz->read($exerciseId);
437
		$tabQuestionList = $quiz->selectQuestionList();
438
		// the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ? ? ?
439
		for ($i=1; $i <= count($tabQuestionList); $i++) {
440
			if (TestCategory::getCategoryForQuestion($tabQuestionList[$i]) == $categoryId) {
441
				$nbCatResult++;
442
			}
443
		}
444
445
		return $nbCatResult;
446
	}
447
448
	/**
449
	 * return the number of question for a test using random by category
450
	 * input  : test_id, number of random question (min 1)
451
	 * hubert.borderiou 07-04-2011
452
	 * question without categories are not counted
453
	 */
454
	public static function getNumberOfQuestionRandomByCategory($exerciseId, $in_nbrandom)
455
    {
456
		$nbquestionresult = 0;
457
		$tabcatid = TestCategory::getListOfCategoriesIDForTest($exerciseId);
458
459
        foreach ($tabcatid as $category) {
460
            if (empty($category['id'])) {
461
                continue;
462
            }
463
464
            $nbQuestionInThisCat = TestCategory::getNumberOfQuestionsInCategoryForTest($exerciseId, $category['id']);
465
466
            if ($nbQuestionInThisCat > $in_nbrandom) {
467
                $nbquestionresult += $in_nbrandom;
468
            } else {
469
                $nbquestionresult += $nbQuestionInThisCat;
470
            }
471
        }
472
473
		return $nbquestionresult;
474
	}
475
476
	/**
477
	 * Return an array (id=>name)
478
	 * tabresult[0] = get_lang('NoCategory');
479
     *
480
     * @param int $courseId
481
     *
482
     * @return array
483
	 *
484
	 */
485
    public static function getCategoriesIdAndName($courseId = "")
486
    {
487
		if (empty($courseId)) {
488
			$courseId = api_get_course_int_id();
489
		}
490
	 	$tabcatobject = TestCategory::getCategoryListInfo("", $courseId);
491
	 	$tabresult = array("0"=>get_lang('NoCategorySelected'));
492
	 	for ($i=0; $i < count($tabcatobject); $i++) {
493
	 		$tabresult[$tabcatobject[$i]->id] = $tabcatobject[$i]->name;
494
	 	}
495
	 	return $tabresult;
496
	}
497
498
    /**
499
     * Returns an array of question ids for each category
500
     * $categories[1][30] = 10, array with category id = 1 and question_id = 10
501
     * A question has "n" categories
502
     * @param int exercise
503
     * @param array $check_in_question_list
504
     * @param array $categoriesAddedInExercise
505
    *
506
    * @param int $exerciseId
507
    * @return array
508
    */
509
    static function getQuestionsByCat(
510
        $exerciseId,
511
        $check_in_question_list = array(),
512
        $categoriesAddedInExercise = array()
513
    ) {
514
        $tableQuestion = Database::get_course_table(TABLE_QUIZ_QUESTION);
515
        $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
516
        $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
517
        $categoryTable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
518
        $exerciseId = intval($exerciseId);
519
        $courseId = api_get_course_int_id();
520
521
        $sql = "SELECT DISTINCT qrc.question_id, qrc.category_id
522
                FROM $TBL_QUESTION_REL_CATEGORY qrc
523
                INNER JOIN $TBL_EXERCICE_QUESTION eq
524
                ON (eq.question_id = qrc.question_id)
525
                INNER JOIN $categoryTable c
526
                ON (c.id = qrc.category_id)
527
                INNER JOIN $tableQuestion q
528
                ON (q.id = qrc.question_id )
529
                WHERE
530
                  exercice_id = $exerciseId AND
531
                  qrc.c_id = ".$courseId."
532
                ";
533
534
        $res = Database::query($sql);
535
        $categories = array();
536
        while ($data = Database::fetch_array($res)) {
537
            if (!empty($check_in_question_list)) {
538
                if (!in_array($data['question_id'], $check_in_question_list)) {
539
                    continue;
540
                }
541
            }
542
543
            if (!isset($categories[$data['category_id']]) ||
544
                !is_array($categories[$data['category_id']])
545
            ) {
546
                $categories[$data['category_id']] = array();
547
            }
548
549
            $categories[$data['category_id']][] = $data['question_id'];
550
        }
551
552
        if (!empty($categoriesAddedInExercise)) {
553
            $newCategoryList = array();
554
            foreach ($categoriesAddedInExercise as $category) {
555
                $categoryId = $category['category_id'];
556
                if (isset($categories[$categoryId])) {
557
                    $newCategoryList[$categoryId] = $categories[$categoryId];
558
                }
559
            }
560
561
            $checkQuestionsWithNoCategory = false;
562
            foreach ($categoriesAddedInExercise as $category) {
563
                if (empty($category['category_id'])) {
564
                    // Check
565
                    $checkQuestionsWithNoCategory = true;
566
                    break;
567
                }
568
            }
569
570
            // Select questions that don't have any category related
571
            if ($checkQuestionsWithNoCategory) {
572
                $originalQuestionList = $check_in_question_list;
573
                foreach ($originalQuestionList as $questionId) {
574
                    $categoriesFlatten = array_flatten($categories);
575
                    if (!in_array($questionId, $categoriesFlatten)) {
576
                        $newCategoryList[0][] = $questionId;
577
                    }
578
                }
579
            }
580
581
            $categories = $newCategoryList;
582
583
        }
584
585
        return $categories;
586
	}
587
588
	/**
589
	 * return a tab of $in_number random elements of $in_tab
590
	 */
591
    public static function getNElementsFromArray($in_tab, $in_number)
592
    {
593
		$tabres = $in_tab;
594
		shuffle($tabres);
595
		if ($in_number < count($tabres)) {
596
			$tabres = array_slice($tabres, 0, $in_number);
597
		}
598
		return $tabres;
599
	}
600
601
	/**
602
	 * display the category
603
	 */
604
	public static function displayCategoryAndTitle($questionId, $in_display_category_name = 1)
605
    {
606
        echo self::returnCategoryAndTitle($questionId, $in_display_category_name);
607
	}
608
609
    /**
610
     * @param int $questionId
611
     * @param int $in_display_category_name
612
     * @return null|string
613
     */
614
    public static function returnCategoryAndTitle($questionId, $in_display_category_name = 1)
615
    {
616
        $is_student = !(api_is_allowed_to_edit(null,true) || api_is_session_admin());
617
        // @todo fix $_SESSION['objExercise']
618
        $objExercise = isset($_SESSION['objExercise']) ? $_SESSION['objExercise'] : null;
619
        if (!empty($objExercise)) {
620
            $in_display_category_name = $objExercise->display_category_name;
621
        }
622
        $content = null;
623
		if (TestCategory::getCategoryNameForQuestion($questionId) != "" && ($in_display_category_name == 1 || !$is_student)) {
624
            $content .= '<div class="page-header">';
625
            $content .= '<h4>'.get_lang('Category').": ".TestCategory::getCategoryNameForQuestion($questionId).'</h4>';
626
            $content .= "</div>";
627
		}
628
        return $content;
629
	}
630
631
    /**
632
    * Display signs [+] and/or (>0) after question title if question has options
633
    * scoreAlwaysPositive and/or uncheckedMayScore
634
    */
635
    public function displayQuestionOption($in_objQuestion)
636
    {
637
		if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->scoreAlwaysPositive) {
638
			echo "<span style='font-size:75%'> (>0)</span>";
639
		}
640
		if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->uncheckedMayScore) {
641
			echo "<span style='font-size:75%'> [+]</span>";
642
		}
643
	}
644
645
	/**
646
	 * sortTabByBracketLabel ($tabCategoryQuestions)
647
	 * key of $tabCategoryQuestions are the category id (0 for not in a category)
648
	 * value is the array of question id of this category
649
	 * Sort question by Category
650
	*/
651
    public static function sortTabByBracketLabel($in_tab)
652
    {
653
		$tabResult = array();
654
		$tabCatName = array();	// tab of category name
655
		while (list($cat_id, $tabquestion) = each($in_tab)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $tabquestion is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
656
			$catTitle = new TestCategory($cat_id);
657
			$tabCatName[$cat_id] = $catTitle->name;
658
		}
659
		reset($in_tab);
660
		// sort table by value, keeping keys as they are
661
		asort($tabCatName);
662
		// keys of $tabCatName are keys order for $in_tab
663
		while (list($key, $val) = each($tabCatName)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $val is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
664
			$tabResult[$key] = $in_tab[$key];
665
		}
666
		return $tabResult;
667
	}
668
669
    /**
670
	 * return total score for test exe_id for all question in the category $in_cat_id for user
671
	 * If no question for this category, return ""
672
	 */
673 View Code Duplication
	public static function getCatScoreForExeidForUserid($in_cat_id, $in_exe_id, $in_user_id)
674
	{
675
		$tbl_track_attempt		= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
676
		$tbl_question_rel_category = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
677
		$in_cat_id = intval($in_cat_id);
678
		$in_exe_id = intval($in_exe_id);
679
		$in_user_id = intval($in_user_id);
680
681
		$query = "SELECT DISTINCT
682
		            marks, exe_id, user_id, ta.question_id, category_id
683
                  FROM $tbl_track_attempt ta , $tbl_question_rel_category qrc
684
                  WHERE
685
                    ta.question_id=qrc.question_id AND
686
                    qrc.category_id=$in_cat_id AND
687
                    exe_id=$in_exe_id AND user_id=$in_user_id";
688
		$res = Database::query($query);
689
		$totalcatscore = "";
690
		while ($data = Database::fetch_array($res)) {
691
			$totalcatscore += $data['marks'];
692
		}
693
		return $totalcatscore;
694
	}
695
696
	/**
697
     * return the number max of question in a category
698
     * count the number of questions in all categories, and return the max
699
     * @param int $exerciseId
700
     * @author - hubert borderiou
701
    */
702
    public static function getNumberMaxQuestionByCat($exerciseId)
703
    {
704
        $res_num_max = 0;
705
        // foreach question
706
		$tabcatid = TestCategory::getListOfCategoriesIDForTest($exerciseId);
707
708
        foreach ($tabcatid as $category) {
709
            if (empty($category['id'])) {
710
                continue;
711
            }
712
713
            $nbQuestionInThisCat = TestCategory::getNumberOfQuestionsInCategoryForTest($exerciseId, $category['id']);
714
715
            if ($nbQuestionInThisCat > $res_num_max) {
716
                $res_num_max = $nbQuestionInThisCat;
717
            }
718
        }
719
        return $res_num_max;
720
    }
721
722
    /**
723
     * Returns a category summary report
724
     * @params int exercise id
725
     * @params array pre filled array with the category_id, score, and weight
726
     * example: array(1 => array('score' => '10', 'total' => 20));
727
     */
728
    public static function get_stats_table_by_attempt($exercise_id, $category_list = array())
729
    {
730
        if (empty($category_list)) {
731
            return null;
732
        }
733
        $category_name_list = TestCategory::getListOfCategoriesNameForTest($exercise_id);
734
735
        $table = new HTML_Table(array('class' => 'data_table'));
736
        $table->setHeaderContents(0, 0, get_lang('Categories'));
737
        $table->setHeaderContents(0, 1, get_lang('AbsoluteScore'));
738
        $table->setHeaderContents(0, 2, get_lang('RelativeScore'));
739
        $row = 1;
740
741
        $none_category = array();
742
        if (isset($category_list['none'])) {
743
            $none_category = $category_list['none'];
744
            unset($category_list['none']);
745
        }
746
747
        $total = array();
748
        if (isset($category_list['total'])) {
749
            $total = $category_list['total'];
750
            unset($category_list['total']);
751
        }
752
        if (count($category_list) > 1) {
753
            foreach ($category_list as $category_id => $category_item) {
754
                $table->setCellContents($row, 0, $category_name_list[$category_id]);
755
                $table->setCellContents($row, 1, ExerciseLib::show_score($category_item['score'], $category_item['total'], false));
756
                $table->setCellContents($row, 2, ExerciseLib::show_score($category_item['score'], $category_item['total'], true, false, true));
757
                $row++;
758
            }
759
760 View Code Duplication
            if (!empty($none_category)) {
761
                $table->setCellContents($row, 0, get_lang('None'));
762
                $table->setCellContents($row, 1, ExerciseLib::show_score($none_category['score'], $none_category['total'], false));
763
                $table->setCellContents($row, 2, ExerciseLib::show_score($none_category['score'], $none_category['total'], true, false, true));
764
                $row++;
765
            }
766 View Code Duplication
            if (!empty($total)) {
767
                $table->setCellContents($row, 0, get_lang('Total'));
768
                $table->setCellContents($row, 1, ExerciseLib::show_score($total['score'], $total['total'], false));
769
                $table->setCellContents($row, 2, ExerciseLib::show_score($total['score'], $total['total'], true, false, true));
770
            }
771
            return $table->toHtml();
772
        }
773
774
        return null;
775
    }
776
777
    /**
778
	 * @return array
779
	 */
780 View Code Duplication
	function get_all_categories()
781
	{
782
		$table = Database::get_course_table(TABLE_QUIZ_CATEGORY);
783
		$sql = "SELECT * FROM $table ORDER BY title ASC";
784
		$res = Database::query($sql);
785
		while ($row = Database::fetch_array($res,'ASSOC')) {
786
			$array[] = $row;
787
		}
788
		return $array;
789
	}
790
791
	/**
792
	 * @param Exercise $exercise
793
	 * @param int $course_id
794
	 * @param string $order
795
	 * @param bool $shuffle
796
	 * @param bool $excludeCategoryWithNoQuestions
797
	 * @return array|bool
798
	 */
799
	public function getCategoryExerciseTree(
800
		$exercise,
801
		$course_id,
802
		$order = null,
803
		$shuffle = false,
804
		$excludeCategoryWithNoQuestions = true
805
	) {
806
        if (empty($exercise)) {
807
            return array();
808
        }
809
810
        if (!$exercise->specialCategoryOrders) {
811
            return false;
812
        }
813
814
        $course_id = intval($course_id);
815
		$table = Database::get_course_table(TABLE_QUIZ_REL_CATEGORY);
816
        $categoryTable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
817
		$sql = "SELECT * FROM $table qc
818
              	LEFT JOIN $categoryTable c
819
                ON (qc.c_id = c.c_id AND c.id = qc.category_id)
820
                WHERE qc.c_id = $course_id AND exercise_id = {$exercise->id} ";
821
822
		if (!empty($order)) {
823
			$sql .= "ORDER BY $order";
824
		}
825
826
		$categories = array();
827
828
		$result = Database::query($sql);
829
		if (Database::num_rows($result)) {
830
			while ($row = Database::fetch_array($result, 'ASSOC')) {
831
				if ($excludeCategoryWithNoQuestions) {
832
					if ($row['count_questions'] == 0) {
833
						continue;
834
					}
835
				}
836
				if (empty($row['title']) && empty($row['category_id'])) {
837
					$row['title'] = get_lang('NoCategory');
838
				}
839
                $categories[$row['category_id']] = $row;
840
			}
841
		}
842
843
		if ($shuffle) {
844
			shuffle_assoc($categories);
845
		}
846
847
		return $categories;
848
	}
849
850
	public function getForm(& $form, $action = 'new')
851
	{
852
		switch($action) {
853
			case 'new':
854
				$header = get_lang('AddACategory');
855
				$submit = get_lang('AddTestCategory');
856
				break;
857
			case 'edit':
858
				$header = get_lang('EditCategory');
859
				$submit = get_lang('ModifyCategory');
860
				break;
861
		}
862
863
		// settting the form elements
864
		$form->addElement('header', $header);
865
		$form->addElement('hidden', 'category_id');
866
		$form->addElement('text', 'category_name', get_lang('CategoryName'), array('class' => 'span6'));
867
		$form->add_html_editor('category_description', get_lang('CategoryDescription'), false, false, array('ToolbarSet' => 'test_category', 'Width' => '90%', 'Height' => '200'));
868
		$category_parent_list = array();
869
870
		$options = array(
871
				'1' => get_lang('Visible'),
872
				'0' => get_lang('Hidden')
873
		);
874
		$form->addElement('select', 'visibility', get_lang('Visibility'), $options);
875
		$script = null;
876
		if (!empty($this->parent_id)) {
877
			$parent_cat = new TestCategory($this->parent_id);
878
			$category_parent_list = array($parent_cat->id => $parent_cat->name);
879
			$script .= '<script>$(function() { $("#parent_id").trigger("addItem",[{"title": "'.$parent_cat->name.'", "value": "'.$parent_cat->id.'"}]); });</script>';
880
		}
881
		$form->addElement('html', $script);
882
883
		$form->addElement('select', 'parent_id', get_lang('Parent'), $category_parent_list, array('id' => 'parent_id'));
884
		$form->addElement('style_submit_button', 'SubmitNote', $submit, 'class="add"');
885
886
		// setting the defaults
887
		$defaults = array();
888
		$defaults["category_id"] = $this->id;
889
		$defaults["category_name"] = $this->name;
890
		$defaults["category_description"] = $this->description;
891
		$defaults["parent_id"] = $this->parent_id;
892
		$defaults["visibility"] = $this->visibility;
893
		$form->setDefaults($defaults);
894
895
		// setting the rules
896
		$form->addRule('category_name', get_lang('ThisFieldIsRequired'), 'required');
897
	}
898
899
	/**
900
	 * Returns the category form.
901
	 * @param Exercise $exercise_obj
902
	 * @return string
903
	 */
904
	public function returnCategoryForm(Exercise $exercise_obj)
905
	{
906
		$categories = $this->getListOfCategoriesForTest($exercise_obj);
907
908
		$saved_categories = $exercise_obj->get_categories_in_exercise();
909
		$return = null;
910
911
		if (!empty($categories)) {
912
			$nbQuestionsTotal = $exercise_obj->getNumberQuestionExerciseCategory();
913
			$exercise_obj->setCategoriesGrouping(true);
914
			$real_question_count = count($exercise_obj->getQuestionList());
915
916
			$warning = null;
917
			if ($nbQuestionsTotal != $real_question_count) {
918
				$warning = Display::return_message(get_lang('CheckThatYouHaveEnoughQuestionsInYourCategories'), 'warning');
919
			}
920
921
			$return .= $warning;
922
			$return .= '<table class="data_table">';
923
			$return .= '<tr>';
924
			$return .= '<th height="24">' . get_lang('Categories') . '</th>';
925
			$return .= '<th width="70" height="24">' . get_lang('Number') . '</th></tr>';
926
927
			$emptyCategory = array(
928
				'id' => '0',
929
				'name' => get_lang('NoCategory'),
930
				'description' => '',
931
				'iid' => '0',
932
				'title' => get_lang('NoCategory')
933
			);
934
935
			$categories[] = $emptyCategory;
936
937
			foreach ($categories as $category) {
938
				$cat_id = $category['iid'];
939
				$return .= '<tr>';
940
				$return .= '<td>';
941
				//$return .= Display::div(isset($category['parent_path']) ? $category['parent_path'] : '');
942
				$return .= Display::div($category['name']);
943
				$return .= '</td>';
944
				$return .= '<td>';
945
				$value = isset($saved_categories) && isset($saved_categories[$cat_id]) ? $saved_categories[$cat_id]['count_questions'] : -1;
946
				$return .= '<input name="category['.$cat_id.']" value="' .$value.'" />';
947
				$return .= '</td>';
948
				$return .= '</tr>';
949
			}
950
951
			$return .= '</table>';
952
			$return .= get_lang('ZeroMeansNoQuestionWillBeSelectedMinusOneMeansThatAllQuestionsWillBeSelected');
953
			return $return;
954
		}
955
	}
956
957
	/**
958
	 * Sorts an array
959
	 * @param $array
960
	 * @return mixed
961
	 */
962
	public function sort_tree_array($array)
963
	{
964
		foreach ($array as $key => $row) {
965
			$parent[$key] = $row['parent_id'];
966
		}
967
		if (count($array) > 0) {
968
			array_multisort($parent, SORT_ASC, $array);
969
		}
970
		return $array;
971
	}
972
973
	/**
974
     * Return true if a category already exists with the same name
975
     * @param string $in_name
976
     *
977
     * @return bool
978
     */
979
    public static function category_exists_with_title($in_name)
980
    {
981
        $tab_test_category = TestCategory::getCategoryListInfo("title");
982
        foreach ($tab_test_category as $title) {
983
            if ($title == $in_name) {
984
                return true;
985
            }
986
        }
987
        return false;
988
    }
989
990
    /**
991
     * Return the id of the test category with title = $in_title
992
     * @param $in_title
993
     * @param int $in_c_id
0 ignored issues
show
Bug introduced by
There is no parameter named $in_c_id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
994
     *
995
     * @return int is id of test category
996
     */
997 View Code Duplication
    public static function get_category_id_for_title($title, $courseId = 0)
998
    {
999
        $out_res = 0;
1000
        if (empty($courseId)) {
1001
            $courseId = api_get_course_int_id();
1002
        }
1003
        $courseId = intval($courseId);
1004
        $tbl_cat = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
1005
        $sql = "SELECT id FROM $tbl_cat
1006
                WHERE c_id = $courseId AND title = '".Database::escape_string($title)."'";
1007
        $res = Database::query($sql);
1008
        if (Database::num_rows($res) > 0) {
1009
            $data = Database::fetch_array($res);
1010
            $out_res = $data['id'];
1011
        }
1012
        return $out_res;
1013
    }
1014
1015
    /**
1016
     * Add a relation between question and category in table c_quiz_question_rel_category
1017
     * @param int $categoryId
1018
     * @param int $questionId
1019
     * @param int $courseId
1020
	 *
1021
	 * @return int
1022
     */
1023
    public static function add_category_for_question_id($categoryId, $questionId, $courseId)
1024
    {
1025
        $table = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
1026
        // if question doesn't have a category
1027
        // @todo change for 1.10 when a question can have several categories
1028
        if (TestCategory::getCategoryForQuestion($questionId, $courseId) == 0 &&
1029
			$questionId > 0 &&
1030
			$courseId > 0
1031
        ) {
1032
            $sql = "INSERT INTO $table (c_id, question_id, category_id)
1033
                    VALUES (".intval($courseId).", ".intval($questionId).", ".intval($categoryId).")";
1034
            Database::query($sql);
1035
			$id = Database::insert_id();
1036
1037
			return $id;
1038
        }
1039
1040
		return false;
1041
    }
1042
1043
    /**
1044
     * @param int $courseId
1045
     * @param int $sessionId
1046
     *
1047
     * @return array
1048
     */
1049
    public function getCategories($courseId, $sessionId = 0)
1050
    {
1051
        $table = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
1052
        $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
1053
        $sessionId = intval($sessionId);
1054
        $courseId = intval($courseId);
1055
1056
        if (empty($sessionId)) {
1057
            $sessionCondition = api_get_session_condition($sessionId, true, false, 'i.session_id');
1058
        } else {
1059
            $sessionCondition = api_get_session_condition($sessionId, true, true, 'i.session_id');
1060
        }
1061
1062
        if (empty($courseId)) {
1063
            return array();
1064
        }
1065
1066
        $sql = "SELECT c.* FROM $table c
1067
                INNER JOIN $itemProperty i
1068
                ON c.c_id = i.c_id AND i.ref = c.id
1069
                WHERE
1070
                    c.c_id = $courseId AND
1071
                    i.tool = '".TOOL_TEST_CATEGORY."'
1072
                    $sessionCondition
1073
                ORDER BY title";
1074
        $result = Database::query($sql);
1075
1076
        return Database::store_result($result, 'ASSOC');
1077
    }
1078
1079
    /**
1080
     * @param int $courseId
1081
     * @param int $sessionId
1082
     * @return string
1083
     */
1084
    public function displayCategories($courseId, $sessionId = 0)
1085
    {
1086
        $categories = $this->getCategories($courseId, $sessionId);
1087
        $html = '';
1088
1089
        foreach ($categories as $category) {
1090
            $tmpobj = new TestCategory($category['id']);
1091
            $nb_question = $tmpobj->getCategoryQuestionsNumber();
1092
            $rowname = self::protectJSDialogQuote($category['title']);
1093
            $nb_question_label = $nb_question == 1 ? $nb_question . ' ' . get_lang('Question') : $nb_question . ' ' . get_lang('Questions');
1094
1095
            //$html .= '<div class="sectiontitle" id="id_cat' . $category['id'] . '">';
1096
            $content = "<span style='float:right'>" . $nb_question_label . "</span>";
1097
1098
            $content .= '<div class="sectioncomment">';
1099
            $content .= $category['description'];
1100
            $content .= '</div>';
1101
1102
            $links = '<a href="' . api_get_self() . '?action=editcategory&category_id=' . $category['id'] . '">' .
1103
                Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL) . '</a>';
1104
            $links .= ' <a href="' . api_get_self() . '?action=deletecategory&category_id=' . $category['id'] . '" ';
1105
            $links .= 'onclick="return confirmDelete(\'' . self::protectJSDialogQuote(get_lang('DeleteCategoryAreYouSure') . '[' . $rowname) . '] ?\', \'id_cat' . $category['id'] . '\');">';
1106
            $links .= Display::return_icon('delete.png', get_lang('Delete'), array(), ICON_SIZE_SMALL) . '</a>';
1107
            $html .= Display::panel($content, $category['title'].$links);
1108
        }
1109
1110
        return $html;
1111
    }
1112
1113
    // To allowed " in javascript dialog box without bad surprises
1114
    // replace " with two '
1115
    public function protectJSDialogQuote($in_txt)
1116
    {
1117
        $res = $in_txt;
1118
        $res = str_replace("'", "\'", $res);
1119
        $res = str_replace('"', "\'\'", $res); // super astuce pour afficher les " dans les boite de dialogue
1120
        return $res;
1121
    }
1122
}
1123