Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

main/gradebook/lib/fe/gradebooktable.class.php (3 issues)

1
<?php
2
3
/* For licensing terms, see license.txt */
4
5
use ChamiloSession as Session;
6
use CpChart\Cache as pCache;
7
use CpChart\Data as pData;
8
use CpChart\Image as pImage;
9
10
/**
11
 * GradebookTable Class
12
 * Table to display categories, evaluations and links.
13
 *
14
 * @author Stijn Konings
15
 * @author Bert Steppé (refactored, optimised)
16
 */
17
class GradebookTable extends SortableTable
18
{
19
    public $cats;
20
    public $exportToPdf;
21
    public $teacherView;
22
    public $userId;
23
    public $studentList = [];
24
    private $currentcat;
25
    private $datagen;
26
    private $evals_links;
27
    private $dataForGraph;
28
    /**
29
     * @var array Indicates which columns should be shown in gradebook
30
     *
31
     * @example [1] For add Ranking column
32
     *          [2] For add Best Score column
33
     *          [3] For add Average column
34
     */
35
    private $loadStats = [];
36
37
    /**
38
     * GradebookTable constructor.
39
     *
40
     * @param Category $currentcat
41
     * @param array    $cats
42
     * @param array    $evals
43
     * @param array    $links
44
     * @param null     $addparams
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $addparams is correct as it would always require null to be passed?
Loading history...
45
     * @param bool     $exportToPdf
46
     * @param null     $showTeacherView
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $showTeacherView is correct as it would always require null to be passed?
Loading history...
47
     * @param int      $userId
48
     * @param array    $studentList
49
     */
50
    public function __construct(
51
        $currentcat,
52
        $cats = [],
53
        $evals = [],
54
        $links = [],
55
        $addparams = null,
56
        $exportToPdf = false,
57
        $showTeacherView = null,
58
        $userId = null,
59
        $studentList = [],
60
        array $loadStats = []
61
    ) {
62
        $this->teacherView = is_null($showTeacherView) ? api_is_allowed_to_edit(null, true) : $showTeacherView;
63
        $this->userId = is_null($userId) ? api_get_user_id() : $userId;
64
        $this->exportToPdf = $exportToPdf;
65
        $this->studentList = $studentList;
66
67
        parent::__construct(
68
            'gradebooklist',
69
            null,
70
            null,
71
            api_is_allowed_to_edit() ? 1 : 0,
72
            1000,
73
            'ASC',
74
            'gradebook_list'
75
        );
76
77
        $this->evals_links = array_merge($evals, $links);
78
        $this->currentcat = $currentcat;
79
        $this->cats = $cats;
80
        $this->loadStats = $loadStats;
81
        $this->datagen = new GradebookDataGenerator($cats, $evals, $links);
82
        $this->datagen->exportToPdf = $this->exportToPdf;
83
        $this->datagen->preLoadDataKey = $this->getPreloadDataKey();
84
        $this->datagen->hidePercentage = api_get_configuration_value('hide_gradebook_percentage_user_result');
85
86
        if (!empty($userId)) {
87
            $this->datagen->userId = $userId;
88
        }
89
90
        if (isset($addparams)) {
91
            $this->set_additional_parameters($addparams);
92
        }
93
94
        $column = 0;
95
        if ($this->teacherView) {
96
            if (false == $this->exportToPdf) {
97
                $this->set_header($column++, '', '', 'width="25px"');
98
            }
99
        }
100
101
        $this->set_header($column++, get_lang('Type'), '', 'width="20px"');
102
        $this->set_header($column++, get_lang('Name'), false);
103
        if (false == $this->exportToPdf) {
104
            $this->set_header($column++, get_lang('Description'), false);
105
        }
106
107
        $model = ExerciseLib::getCourseScoreModel();
108
        $settings = api_get_configuration_value('gradebook_pdf_export_settings');
109
        $showWeight = true;
110
        if ($this->exportToPdf && isset($settings['hide_score_weight']) && $settings['hide_score_weight']) {
111
            $showWeight = false;
112
        }
113
        if ($showWeight) {
114
            $this->set_header(
115
                $column++,
116
                get_lang('Weight'),
117
                '',
118
                'width="100px"'
119
            );
120
        }
121
122
        if (!$this->teacherView) {
123
            $this->set_header($column++, get_lang('Result'), false);
124
        }
125
126
        if (empty($model)) {
127
            if (in_array(1, $this->loadStats)) {
128
                $this->set_header($column++, get_lang('Ranking'), false, 'width="80px"');
129
            }
130
            if (in_array(2, $this->loadStats)) {
131
                $this->set_header($column++, get_lang('BestScore'), false, 'width="120px"');
132
            }
133
            if (in_array(3, $this->loadStats)) {
134
                $this->set_header($column++, get_lang('Average'), false, 'width="120px"');
135
            }
136
        }
137
138
        if ($this->teacherView) {
139
        } else {
140
            if (!empty($cats)) {
141
                if ($this->exportToPdf == false) {
142
                    $this->set_header($column++, get_lang('Actions'), false);
143
                }
144
            }
145
        }
146
147
        // Deactivates the odd/even alt rows in order that the +/- buttons work see #4047
148
        $this->odd_even_rows_enabled = false;
149
150
        // Admins get an edit column.
151
        if ($this->teacherView) {
152
            $this->set_header($column++, get_lang('Modify'), false, 'width="195px"');
153
            // Actions on multiple selected documents.
154
            $this->set_form_actions(
155
                [
156
                    'setvisible' => get_lang('SetVisible'),
157
                    'setinvisible' => get_lang('SetInvisible'),
158
                    'deleted' => get_lang('DeleteSelected'),
159
                ]
160
            );
161
        } else {
162
            if (empty($_GET['selectcat']) && !$this->teacherView) {
163
                if ($this->exportToPdf == false) {
164
                    $this->set_header(
165
                        $column++,
166
                        get_lang('Certificates'),
167
                        false
168
                    );
169
                }
170
            }
171
        }
172
    }
173
174
    /**
175
     * @return GradebookDataGenerator
176
     */
177
    public function get_data()
178
    {
179
        return $this->datagen;
180
    }
181
182
    /**
183
     * Function used by SortableTable to get total number of items in the table.
184
     *
185
     * @return int
186
     */
187
    public function get_total_number_of_items()
188
    {
189
        return $this->datagen->get_total_items_count();
190
    }
191
192
    /**
193
     * @return string
194
     */
195
    public function getPreloadDataKey()
196
    {
197
        return 'default_data_'.api_get_course_id().'_'.api_get_session_id();
198
    }
199
200
    public function preloadData()
201
    {
202
        $allitems = $this->datagen->items;
203
        usort($allitems, ['GradebookDataGenerator', 'sort_by_name']);
204
        $visibleItems = array_merge($this->datagen->items, $this->evals_links);
205
        $defaultDataFromSession = Session::read($this->getPreloadDataKey());
206
        if (empty($defaultDataFromSession)) {
207
            $defaultData = [];
208
            /** @var GradebookItem $item */
209
            foreach ($visibleItems as $item) {
210
                $item->setStudentList($this->studentList);
211
                $itemType = get_class($item);
212
                switch ($itemType) {
213
                    case 'Evaluation':
214
                        // Best
215
                        $best = $this->datagen->buildBestResultColumn($item);
216
                        $defaultData[$item->get_id()]['best'] = $best;
217
                        // Average
218
                        $average = $this->datagen->buildAverageResultColumn($item);
219
                        $defaultData[$item->get_id()]['average'] = $average;
220
                        break;
221
                    case 'ExerciseLink':
222
                        /** @var ExerciseLink $item */
223
                        // Best
224
                        $best = $this->datagen->buildBestResultColumn($item);
225
                        $defaultData[$item->get_id()]['best'] = $best;
226
                        // Average
227
                        $average = $this->datagen->buildAverageResultColumn($item);
228
                        $defaultData[$item->get_id()]['average'] = $average;
229
                        // Ranking
230
                        /*if (!empty($this->studentList)) {
231
                            $invalidateRanking = true;
232
                            foreach ($this->studentList as $user) {
233
                                $score = $this->datagen->build_result_column(
234
                                    $user['user_id'],
235
                                    $item,
236
                                    false,
237
                                    true
238
                                );
239
                                if (!empty($score['score'])) {
240
                                    $invalidateRanking = false;
241
                                }
242
                                $rankingStudentList[$user['user_id']] = $score['score'][0];
243
                                $defaultData[$item->get_id()]['ranking'] = $rankingStudentList;
244
                                $defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateRanking;
245
                            }
246
                        }*/
247
                        break;
248
                    default:
249
                        // Best
250
                        $best = $this->datagen->buildBestResultColumn($item);
251
                        $defaultData[$item->get_id()]['best'] = $best;
252
253
                        // Average
254
                        $average = $this->datagen->buildAverageResultColumn($item);
255
                        $defaultData[$item->get_id()]['average'] = $average;
256
257
                        // Ranking
258
                        if (!empty($this->studentList)) {
259
                            $invalidateRanking = true;
260
                            foreach ($this->studentList as $user) {
261
                                $score = $this->datagen->build_result_column(
262
                                    $user['user_id'],
263
                                    $item,
264
                                    false,
265
                                    true
266
                                );
267
                                if (!empty($score['score'])) {
268
                                    $invalidateRanking = false;
269
                                }
270
                                $rankingStudentList[$user['user_id']] = $score['score'][0];
271
                                $defaultData[$item->get_id()]['ranking'] = $rankingStudentList;
272
                                $defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateRanking;
273
                            }
274
                        }
275
                        break;
276
                }
277
            }
278
            Session::write($this->getPreloadDataKey(), $defaultData);
279
        } else {
280
            $defaultData = $defaultDataFromSession;
281
        }
282
283
        return $defaultData;
284
    }
285
286
    /**
287
     * Function used by SortableTable to generate the data to display.
288
     *
289
     * @param int    $from
290
     * @param int    $per_page
291
     * @param int    $column
292
     * @param string $direction
293
     * @param int    $sort
294
     *
295
     * @return array|mixed
296
     */
297
    public function get_table_data($from = 1, $per_page = null, $column = null, $direction = null, $sort = null)
298
    {
299
        //variables load in index.php
300
        global $certificate_min_score;
301
302
        $isAllowedToEdit = api_is_allowed_to_edit();
303
        // determine sorting type
304
        $col_adjust = $isAllowedToEdit ? 1 : 0;
305
        // By id
306
        $this->column = 5;
307
308
        switch ($this->column) {
309
            // Type
310
            case 0 + $col_adjust:
311
                $sorting = GradebookDataGenerator::GDG_SORT_TYPE;
312
                break;
313
            case 1 + $col_adjust:
314
                $sorting = GradebookDataGenerator::GDG_SORT_NAME;
315
                break;
316
            case 2 + $col_adjust:
317
                $sorting = GradebookDataGenerator::GDG_SORT_DESCRIPTION;
318
                break;
319
            case 3 + $col_adjust:
320
                $sorting = GradebookDataGenerator::GDG_SORT_WEIGHT;
321
                break;
322
            case 4 + $col_adjust:
323
                $sorting = GradebookDataGenerator::GDG_SORT_DATE;
324
                break;
325
            case 5 + $col_adjust:
326
                $sorting = GradebookDataGenerator::GDG_SORT_ID;
327
                break;
328
        }
329
330
        if ('DESC' === $this->direction) {
331
            $sorting |= GradebookDataGenerator::GDG_SORT_DESC;
332
        } else {
333
            $sorting |= GradebookDataGenerator::GDG_SORT_ASC;
334
        }
335
336
        // Status of user in course.
337
        $user_id = $this->userId;
338
        $course_code = api_get_course_id();
339
        $session_id = api_get_session_id();
340
341
        $statusToFilter = 0;
342
        if (empty($session_id)) {
343
            $statusToFilter = STUDENT;
344
        }
345
346
        if (empty($this->studentList) && $this->loadStats) {
347
            $studentList = CourseManager::get_user_list_from_course_code(
348
                $course_code,
349
                $session_id,
350
                null,
351
                null,
352
                $statusToFilter
353
            );
354
            $this->studentList = $studentList;
355
        }
356
357
        $this->datagen->userId = $this->userId;
358
        $data_array = $this->datagen->get_data(
359
            $sorting,
360
            $from,
361
            $this->per_page,
362
            false,
363
            $this->studentList,
364
            $this->loadStats
365
        );
366
367
        // generate the data to display
368
        $sortable_data = [];
369
        $weight_total_links = 0;
370
        $main_cat = Category::load(
371
            null,
372
            null,
373
            $course_code,
374
            null,
375
            null,
376
            $session_id,
377
            'ORDER BY id'
378
        );
379
380
        $total_categories_weight = 0;
381
        $scoredisplay = ScoreDisplay::instance();
382
        $totalBest = [0, 0];
383
        $totalAverage = [0, 0];
384
385
        $type = 'detail';
386
        if ($this->exportToPdf) {
387
            $type = 'simple';
388
        }
389
390
        $model = ExerciseLib::getCourseScoreModel();
391
        $userExerciseScoreInCategory = api_get_configuration_value(
392
            'gradebook_use_exercise_score_settings_in_categories'
393
        );
394
        $useExerciseScoreInTotal = api_get_configuration_value('gradebook_use_exercise_score_settings_in_total');
395
        $course_code = api_get_course_id();
396
        $session_id = api_get_session_id();
397
        $defaultData = Session::read($this->getPreloadDataKey());
398
        $settings = api_get_configuration_value('gradebook_pdf_export_settings');
399
        $showWeight = true;
400
        if ($this->exportToPdf && isset($settings['hide_score_weight']) && $settings['hide_score_weight']) {
401
            $showWeight = false;
402
        }
403
        $totalAverageList = [];
404
        // Categories.
405
        if (!empty($data_array)) {
406
            foreach ($data_array as $data) {
407
                // list of items inside the gradebook (exercises, lps, forums, etc)
408
                $row = [];
409
                /** @var AbstractLink $item */
410
                $item = $data[0];
411
                // If the item is invisible, wrap it in a span with class invisible
412
                $invisibility_span_open = $isAllowedToEdit && $item->is_visible() == '0' ? '<span class="text-muted">' : '';
413
                $invisibility_span_close = $isAllowedToEdit && $item->is_visible() == '0' ? '</span>' : '';
414
415
                if ($this->teacherView) {
416
                    if (false == $this->exportToPdf) {
417
                        $row[] = $this->build_id_column($item);
418
                    }
419
                }
420
421
                // Type.
422
                $row[] = $this->build_type_column($item);
423
424
                // Name.
425
                if ('Category' === get_class($item)) {
426
                    $row[] = $invisibility_span_open.
427
                        '<strong>'.Security::remove_XSS($item->get_name()).'</strong>'.$invisibility_span_close;
428
                    $main_categories[$item->get_id()]['name'] = $item->get_name();
429
                } else {
430
                    $name = Security::remove_XSS($this->build_name_link($item, $type));
431
                    $row[] = $invisibility_span_open.$name.$invisibility_span_close;
432
                    $main_categories[$item->get_id()]['name'] = $name;
433
                }
434
435
                $this->dataForGraph['categories'][] = $item->get_name();
436
                $main_categories[$item->get_id()]['weight'] = $item->get_weight();
437
                $total_categories_weight += $item->get_weight();
438
439
                // Description.
440
                if (false == $this->exportToPdf) {
441
                    $row[] = $invisibility_span_open.$data[2].$invisibility_span_close;
442
                }
443
444
                // Weight.
445
                $weight = $scoredisplay->display_score(
446
                    [
447
                        $data['3'],
448
                        $this->currentcat->get_weight(),
449
                    ],
450
                    SCORE_SIMPLE,
451
                    SCORE_BOTH,
452
                    true
453
                );
454
455
                if ($showWeight) {
456
                    if ($this->teacherView) {
457
                        $row[] = $invisibility_span_open.
458
                            Display::tag('p', $weight, ['class' => 'score']).
459
                            $invisibility_span_close;
460
                    } else {
461
                        $row[] = $invisibility_span_open.$weight.$invisibility_span_close;
462
                    }
463
                }
464
465
                $category_weight = $item->get_weight();
466
                if ($this->teacherView) {
467
                    $weight_total_links += $data[3];
468
                }
469
470
                // Edit (for admins).
471
                if ($this->teacherView) {
472
                    $cat = new Category();
473
                    $show_message = $cat->show_message_resource_delete($item->get_course_code());
474
                    if ($show_message === false) {
475
                        $row[] = $this->build_edit_column($item);
476
                    }
477
                } else {
478
                    // Students get the results and certificates columns
479
                    $value_data = isset($data[4]) ? $data[4] : null;
480
                    $best = isset($data['best']) ? $data['best'] : null;
481
                    $average = isset($data['average']) ? $data['average'] : null;
482
                    $ranking = isset($data['ranking']) ? $data['ranking'] : null;
483
484
                    $totalResult = [
485
                        $data['result_score'][0],
486
                        $data['result_score'][1],
487
                    ];
488
489
                    if (empty($model)) {
490
                        $totalBest = [
491
                            $scoredisplay->format_score($totalBest[0] + $data['best_score'][0]),
492
                            $scoredisplay->format_score($totalBest[1] + $data['best_score'][1]),
493
                        ];
494
                        $totalAverage = [0, 0];
495
                        if (isset($data['average_score']) && !empty($data['average_score'])) {
496
                            $totalAverage = [
497
                                $data['average_score'][0],
498
                                $data['average_score'][1],
499
                            ];
500
                        }
501
                    }
502
503
                    // Score
504
                    if (empty($model)) {
505
                        $row[] = $value_data;
506
                    } else {
507
                        $row[] = ExerciseLib::show_score(
508
                            $data['result_score'][0],
509
                            $data['result_score'][1]
510
                        );
511
                    }
512
513
                    $totalAverageList[$item->get_id()] = $totalAverage;
514
                    $mode = SCORE_AVERAGE;
515
                    if ($userExerciseScoreInCategory) {
516
                        $mode = SCORE_SIMPLE;
517
                        $result = ExerciseLib::convertScoreToPlatformSetting($totalAverage[0], $totalAverage[1]);
518
                        $totalAverage[0] = $result['score'];
519
                        $totalAverage[1] = $result['weight'];
520
521
                        $result = ExerciseLib::convertScoreToPlatformSetting($totalResult[0], $totalResult[1]);
522
                        $totalResult[0] = $result['score'];
523
                        $totalResult[1] = $result['weight'];
524
525
                        $result = ExerciseLib::convertScoreToPlatformSetting(
526
                            $data['result_score'][0],
527
                            $data['result_score'][1]
528
                        );
529
                        $data['my_result_no_float'][0] = $result['score'];
530
                    }
531
532
                    $totalResultAverageValue = strip_tags(
533
                        $scoredisplay->display_score($totalResult, $mode, null, false, false, true)
534
                    );
535
                    $totalAverageValue = strip_tags(
536
                        $scoredisplay->display_score($totalAverage, $mode, null, false, false, true)
537
                    );
538
539
                    $this->dataForGraph['my_result'][] = floatval($totalResultAverageValue);
540
                    $this->dataForGraph['average'][] = floatval($totalAverageValue);
541
                    $this->dataForGraph['my_result_no_float'][] = $data['result_score'][0];
542
543
                    if (empty($model)) {
544
                        // Ranking
545
                        if (in_array(1, $this->loadStats)) {
546
                            $row[] = $ranking;
547
                        }
548
549
                        // Best
550
                        if (in_array(2, $this->loadStats)) {
551
                            $row[] = $best;
552
                        }
553
554
                        // Average
555
                        if (in_array(3, $this->loadStats)) {
556
                            $row[] = $average;
557
                        }
558
                    }
559
560
                    if ('Category' === get_class($item)) {
561
                        if (false == $this->exportToPdf) {
562
                            $row[] = $this->build_edit_column($item);
563
                        }
564
                    }
565
                }
566
567
                // Category added.
568
                $sortable_data[] = $row;
569
570
                // Loading children
571
                if ('Category' === get_class($item)) {
572
                    $parent_id = $item->get_id();
573
                    $cats = Category::load(
574
                        $parent_id,
575
                        null,
576
                        null,
577
                        null,
578
                        null,
579
                        null
580
                    );
581
582
                    if (isset($cats[0])) {
583
                        /** @var Category $subCategory */
584
                        $subCategory = $cats[0];
585
                        $allcat = $subCategory->get_subcategories($this->userId, $course_code, $session_id);
586
                        $alleval = $subCategory->get_evaluations($this->userId);
587
                        $alllink = $subCategory->get_links($this->userId);
588
589
                        $sub_cat_info = new GradebookDataGenerator($allcat, $alleval, $alllink);
590
                        $sub_cat_info->exportToPdf = $this->exportToPdf;
591
                        $sub_cat_info->preLoadDataKey = $this->getPreloadDataKey();
592
                        $sub_cat_info->userId = $user_id;
593
594
                        $data_array2 = $sub_cat_info->get_data(
595
                            $sorting,
596
                            $from,
597
                            $this->per_page,
598
                            false,
599
                            $this->studentList
600
                        );
601
                        $total_weight = 0;
602
603
                        // Links.
604
                        foreach ($data_array2 as $data) {
605
                            $row = [];
606
                            $item = $data[0];
607
                            // if the item is invisible, wrap it in a span with class invisible
608
                            $invisibility_span_open = $isAllowedToEdit && $item->is_visible() == '0' ? '<span class="text-muted">' : '';
609
                            $invisibility_span_close = $isAllowedToEdit && $item->is_visible() == '0' ? '</span>' : '';
610
611
                            if (isset($item)) {
612
                                $main_categories[$parent_id]['children'][$item->get_id()]['name'] = $item->get_name();
613
                                $main_categories[$parent_id]['children'][$item->get_id()]['weight'] = $item->get_weight();
614
                            }
615
616
                            if ($this->teacherView) {
617
                                if (false == $this->exportToPdf) {
618
                                    $row[] = $this->build_id_column($item);
619
                                }
620
                            }
621
622
                            // Type
623
                            $row[] = $this->build_type_column($item, ['style' => 'padding-left:5px']);
624
                            // Name.
625
                            $row[] = $invisibility_span_open.'&nbsp;&nbsp;&nbsp; '.
626
                                Security::remove_XSS($this->build_name_link($item, $type, 4)).$invisibility_span_close;
627
628
                            // Description.
629
                            if (false == $this->exportToPdf) {
630
                                $row[] = $invisibility_span_open.$data[2].$invisibility_span_close;
631
                            }
632
633
                            $weight = $data[3];
634
                            $total_weight += $weight;
635
636
                            // Weight
637
                            if ($showWeight) {
638
                                $row[] = $invisibility_span_open.$weight.$invisibility_span_close;
639
                            }
640
641
                            // Admins get an edit column.
642
                            if (api_is_allowed_to_edit(null, true) &&
643
                                isset($_GET['user_id']) == false &&
644
                                (isset($_GET['action']) && $_GET['action'] != 'export_all' || !isset($_GET['action']))
645
                            ) {
646
                                $cat = new Category();
647
                                $show_message = $cat->show_message_resource_delete($item->get_course_code());
648
                                if ($show_message === false) {
649
                                    if ($this->exportToPdf == false) {
650
                                        $row[] = $this->build_edit_column($item);
651
                                    }
652
                                }
653
                            } else {
654
                                // Students get the results and certificates columns
655
                                $eval_n_links = array_merge($alleval, $alllink);
656
                                if (count($eval_n_links) > 0) {
657
                                    $value_data = isset($data[4]) ? $data[4] : null;
658
                                    if (!is_null($value_data)) {
659
                                        // Result
660
                                        $row[] = $value_data;
661
                                        $best = isset($data['best']) ? $data['best'] : null;
662
                                        $average = isset($data['average']) ? $data['average'] : null;
663
                                        $ranking = isset($data['ranking']) ? $data['ranking'] : null;
664
                                        if (empty($model)) {
665
                                            // Ranking
666
                                            if (in_array(1, $this->loadStats)) {
667
                                                $row[] = $ranking;
668
                                            }
669
670
                                            // Best
671
                                            if (in_array(2, $this->loadStats)) {
672
                                                $row[] = $best;
673
                                            }
674
675
                                            // Average
676
                                            if (in_array(3, $this->loadStats)) {
677
                                                $row[] = $average;
678
                                            }
679
                                        }
680
                                    }
681
                                }
682
683
                                if (!empty($cats)) {
684
                                    if (false == $this->exportToPdf) {
685
                                        $row[] = null;
686
                                    }
687
                                }
688
                            }
689
690
                            if (false == $this->exportToPdf) {
691
                                $row['child_of'] = $parent_id;
692
                            }
693
                            $sortable_data[] = $row;
694
                        }
695
696
                        // "Warning row"
697
                        if (!empty($data_array)) {
698
                            if ($this->teacherView) {
699
                                // Compare the category weight to the sum of all weights inside the category
700
                                if (intval($total_weight) == $category_weight) {
701
                                    $label = null;
702
                                    $total = GradebookUtils::score_badges(
703
                                        [
704
                                            $total_weight.' / '.$category_weight,
705
                                            '100',
706
                                        ]
707
                                    );
708
                                } else {
709
                                    $label = Display::return_icon(
710
                                        'warning.png',
711
                                        sprintf(get_lang('TotalWeightMustBeX'), $category_weight)
712
                                    );
713
                                    $total = Display::badge($total_weight.' / '.$category_weight, 'warning');
714
                                }
715
                                $row = [
716
                                    null,
717
                                    null,
718
                                    "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>".get_lang('SubTotal').'</h5>',
719
                                    null,
720
                                    $total.' '.$label,
721
                                    'child_of' => $parent_id,
722
                                ];
723
                                $sortable_data[] = $row;
724
                            }
725
                        }
726
                    }
727
                }
728
            }
729
        } //end looping categories
730
731
        $main_weight = 0;
732
        if (count($main_cat) > 1) {
733
            /** @var Category $myCat */
734
            foreach ($main_cat as $myCat) {
735
                $myParentId = $myCat->get_parent_id();
736
                if (0 == $myParentId) {
737
                    $main_weight = (int) $myCat->get_weight();
738
                }
739
            }
740
        }
741
742
        if ($this->teacherView) {
743
            // Total for teacher.
744
            if (count($main_cat) > 1) {
745
                if (intval($total_categories_weight) == $main_weight) {
746
                    $total = GradebookUtils::score_badges(
747
                        [
748
                            $total_categories_weight.' / '.$main_weight,
749
                            '100',
750
                        ]
751
                    );
752
                } else {
753
                    $total = Display::badge($total_categories_weight.' / '.$main_weight, 'warning');
754
                }
755
                $row = [
756
                    null,
757
                    null,
758
                    '<strong>'.get_lang('Total').'</strong>',
759
                    null,
760
                    $total,
761
                ];
762
                $sortable_data[] = $row;
763
            }
764
        } else {
765
            $showPercentage = false === $this->datagen->hidePercentage;
766
            // Total for student.
767
            if (count($main_cat) > 1) {
768
                $main_weight = (int) $main_cat[0]->get_weight();
769
                $global = null;
770
                $average = null;
771
                $myTotal = 0;
772
                foreach ($this->dataForGraph['my_result_no_float'] as $result) {
773
                    $myTotal += $result;
774
                }
775
776
                $totalResult[0] = $myTotal;
777
                // Overwrite main weight
778
                $totalResult[1] = $main_weight;
779
780
                if (!empty($model)) {
781
                    $totalResult = ExerciseLib::show_score(
782
                        $totalResult[0],
783
                        $totalResult[1]
784
                    );
785
                } else {
786
                    $totalResult = $scoredisplay->display_score(
787
                        $totalResult,
788
                        SCORE_DIV,
789
                        null,
790
                        false,
791
                        false,
792
                        true
793
                    );
794
795
                    if ($useExerciseScoreInTotal) {
796
                        $totalResult = ExerciseLib::show_score($myTotal, $main_weight, false);
797
                    }
798
                }
799
800
                $row = [
801
                    null,
802
                    '<strong>'.get_lang('Total').'</strong>',
803
                ];
804
805
                if (!$this->exportToPdf) {
806
                    $row[] = null;
807
                }
808
809
                if ($showWeight) {
810
                    $row[] = $main_weight;
811
                }
812
813
                $row[] = $totalResult;
814
                $categoryId = $main_cat[0]->get_id();
815
816
                if (empty($model)) {
817
                    if (in_array(1, $this->loadStats)) {
818
                        if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['ranking'])) {
819
                            $totalRanking = $defaultData[$categoryId]['ranking'];
820
                            $invalidateRanking = $defaultData[$categoryId]['ranking_invalidate'];
821
                            $average = 0;
822
                            foreach ($totalRanking as $ranking) {
823
                                $average += $ranking;
824
                            }
825
                        } else {
826
                            $totalRanking = [];
827
                            $invalidateRanking = true;
828
                            $average = 0;
829
                            $main_cat[0]->setStudentList($this->studentList);
830
                            foreach ($this->studentList as $student) {
831
                                $score = $main_cat[0]->calc_score(
832
                                    $student['user_id'],
833
                                    null,
834
                                    $course_code,
835
                                    $session_id
836
                                );
837
                                if (!empty($score[0])) {
838
                                    $invalidateRanking = false;
839
                                }
840
                                $totalRanking[$student['user_id']] = $score[0];
841
                                $average += $score[0];
842
                            }
843
                            $defaultData[$categoryId]['ranking'] = $totalRanking;
844
                            $defaultData[$categoryId]['ranking_invalidate'] = $invalidateRanking;
845
                            Session::write($this->getPreloadDataKey(), $defaultData);
846
                        }
847
848
                        $totalRanking = AbstractLink::getCurrentUserRanking($user_id, $totalRanking);
849
                        $totalRanking = $scoredisplay->display_score(
850
                            $totalRanking,
851
                            SCORE_DIV,
852
                            SCORE_BOTH,
853
                            true,
854
                            true,
855
                            true
856
                        );
857
858
                        if ($invalidateRanking) {
859
                            $totalRanking = null;
860
                        }
861
                        $row[] = $totalRanking;
862
                    }
863
864
                    if (in_array(2, $this->loadStats)) {
865
                        if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['best'])) {
866
                            $totalBest = $defaultData[$categoryId]['best'];
867
                        } else {
868
                            // Overwrite main weight
869
                            $totalBest[1] = $main_weight;
870
                            $defaultData[$categoryId]['best'] = $totalBest;
871
                        }
872
873
                        if ($useExerciseScoreInTotal) {
874
                            if (isset($totalBest['score'])) {
875
                                $totalBestScore = $totalBest['score'];
876
                            } else {
877
                                $totalBestScore = $totalBest;
878
                            }
879
880
                            $totalBest = ExerciseLib::show_score($totalBestScore[0], $totalBestScore[1], $showPercentage);
881
                        } else {
882
                            $totalBest = $scoredisplay->display_score(
883
                                $totalBest,
884
                                SCORE_DIV,
885
                                SCORE_BOTH,
886
                                true,
887
                                false,
888
                                true
889
                            );
890
                        }
891
                        $row[] = $totalBest;
892
                    }
893
894
                    if (in_array(3, $this->loadStats)) {
895
                        if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['average'])) {
896
                            $totalAverage = $defaultData[$categoryId]['average'];
897
                        } else {
898
                            $averageWeight = 0;
899
                            $categoryAverage = 0;
900
                            foreach ($totalAverageList as $averageScore) {
901
                                $categoryAverage += $averageScore[0];
902
                                $averageWeight += $averageScore[1];
903
                            }
904
                            $categoryAverage = $categoryAverage / count($totalAverageList);
905
                            //$averageWeight = $averageWeight ($totalAverageList);
906
907
                            // Overwrite main weight
908
                            //$totalAverage[0] = $average / count($this->studentList);
909
                            //$totalAverage[1] = $main_weight;
910
                            $totalAverage[0] = $categoryAverage;
911
                            $totalAverage[1] = $averageWeight;
912
                            //$defaultData[$categoryId]['average'] = $totalBest;
913
                        }
914
915
                        if ($useExerciseScoreInTotal) {
916
                            if (isset($totalAverage['score'])) {
917
                                $totalAverageScore = $totalAverage['score'];
918
                            } else {
919
                                $totalAverageScore = $totalAverage;
920
                            }
921
922
                            $totalAverage = ExerciseLib::show_score($totalAverageScore[0], $totalAverageScore[1], $showPercentage);
923
                        } else {
924
                            $totalAverage = $scoredisplay->display_score(
925
                                $totalAverage,
926
                                SCORE_DIV,
927
                                SCORE_BOTH,
928
                                true,
929
                                false,
930
                                true
931
                            );
932
                        }
933
934
                        $row[] = $totalAverage;
935
                    }
936
                }
937
938
                if (!empty($row)) {
939
                    $sortable_data[] = $row;
940
                }
941
            }
942
        }
943
944
        Session::write('default_data', $defaultData);
945
946
        // Warning messages
947
        $view = isset($_GET['view']) ? $_GET['view'] : null;
948
        if ($this->teacherView) {
949
            if (isset($_GET['selectcat']) &&
950
                $_GET['selectcat'] > 0 &&
951
                $view !== 'presence'
952
            ) {
953
                $id_cat = (int) $_GET['selectcat'];
954
                $category = Category::load($id_cat);
955
                $weight_category = (int) $this->build_weight($category[0]);
956
                $course_code = $this->build_course_code($category[0]);
957
                $weight_total_links = round($weight_total_links);
958
959
                if ($weight_total_links > $weight_category ||
960
                    $weight_total_links < $weight_category ||
961
                    $weight_total_links > $weight_category
962
                ) {
963
                    $warning_message = sprintf(get_lang('TotalWeightMustBeX'), $weight_category);
964
                    $modify_icons =
965
                        '<a
966
                        href="gradebook_edit_cat.php?editcat='.$id_cat.'&cidReq='.$course_code.'&id_session='.api_get_session_id().'">'.
967
                        Display::return_icon('edit.png', $warning_message, [], ICON_SIZE_SMALL).'</a>';
968
                    $warning_message .= $modify_icons;
969
                    echo Display::return_message($warning_message, 'warning', false);
970
                }
971
972
                $content_html = DocumentManager::replace_user_info_into_html(
973
                    api_get_user_id(),
974
                    $course_code,
975
                    api_get_session_id()
976
                );
977
978
                if (!empty($content_html)) {
979
                    $new_content = explode('</head>', $content_html['content']);
980
                }
981
982
                if (empty($new_content[0])) {
983
                    // Set default certificate
984
                    $courseData = api_get_course_info($course_code);
985
                    DocumentManager::generateDefaultCertificate($courseData);
986
                }
987
            }
988
989
            if (empty($_GET['selectcat'])) {
990
                $categories = Category::load();
991
                $weight_categories = $certificate_min_scores = $course_codes = [];
992
                foreach ($categories as $category) {
993
                    $course_code_category = $this->build_course_code($category);
994
                    if (!empty($course_code)) {
995
                        if ($course_code_category == $course_code) {
996
                            $weight_categories[] = intval($this->build_weight($category));
997
                            $certificate_min_scores[] = intval($this->build_certificate_min_score($category));
998
                            $course_codes[] = $course_code;
999
                            break;
1000
                        }
1001
                    } else {
1002
                        $weight_categories[] = intval($this->build_weight($category));
1003
                        $certificate_min_scores[] = intval($this->build_certificate_min_score($category));
1004
                        $course_codes[] = $course_code_category;
1005
                    }
1006
                }
1007
1008
                if (is_array($weight_categories) &&
1009
                    is_array($certificate_min_scores) &&
1010
                    is_array($course_codes)
1011
                ) {
1012
                    $warning_message = '';
1013
                    for ($x = 0; $x < count($weight_categories); $x++) {
0 ignored issues
show
Performance Best Practice introduced by
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...
1014
                        $weight_category = intval($weight_categories[$x]);
1015
                        $certificate_min_score = intval($certificate_min_scores[$x]);
1016
                        $course_code = $course_codes[$x];
1017
1018
                        if (empty($certificate_min_score) ||
1019
                            ($certificate_min_score > $weight_category)
1020
                        ) {
1021
                            $warning_message .= $course_code.
1022
                                '&nbsp;-&nbsp;'.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan').
1023
                                '&nbsp;'.$weight_category.'<br />';
1024
                        }
1025
                    }
1026
1027
                    if (!empty($warning_message)) {
1028
                        echo Display::return_message($warning_message, 'warning', false);
1029
                    }
1030
                }
1031
            }
1032
        }
1033
1034
        return $sortable_data;
1035
    }
1036
1037
    /**
1038
     * @return string
1039
     */
1040
    public function getGraph()
1041
    {
1042
        $data = $this->getDataForGraph();
1043
        if (!empty($data) &&
1044
            isset($data['categories']) &&
1045
            isset($data['my_result']) &&
1046
            isset($data['average'])
1047
        ) {
1048
            $dataSet = new pData();
1049
            $dataSet->addPoints($data['my_result'], get_lang('Me'));
1050
            // In order to generate random values
1051
            // $data['average'] = array(rand(0,50), rand(0,50));
1052
            $dataSet->addPoints($data['average'], get_lang('Average'));
1053
            $dataSet->addPoints($data['categories'], 'categories');
1054
            $dataSet->setAbscissa('categories');
1055
            $xSize = 700;
1056
            $ySize = 500;
1057
            $pChart = new pImage($xSize, $ySize, $dataSet);
1058
            /* Turn of Antialiasing */
1059
            $pChart->Antialias = false;
1060
1061
            /* Add a border to the picture */
1062
            $pChart->drawRectangle(
1063
                0,
1064
                0,
1065
                $xSize - 1,
1066
                $ySize - 1,
1067
                ["R" => 0, "G" => 0, "B" => 0]
1068
            );
1069
            $pChart->drawText(
1070
                80,
1071
                16,
1072
                get_lang('Results'),
1073
                ["FontSize" => 11, "Align" => TEXT_ALIGN_BOTTOMMIDDLE]
1074
            );
1075
            $pChart->setGraphArea(50, 30, $xSize - 50, $ySize - 70);
1076
            $pChart->setFontProperties(
1077
                [
1078
                    'FontName' => api_get_path(SYS_FONTS_PATH).'Harmattan/Harmattan-Regular.ttf',
1079
                    /*'FontName' => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',*/
1080
                    'FontSize' => 10,
1081
                ]
1082
            );
1083
1084
            /* Draw the scale */
1085
            $scaleSettings = [
1086
                "XMargin" => AUTO,
1087
                "YMargin" => 10,
1088
                "Floating" => true,
1089
                "GridR" => 200,
1090
                "GridG" => 200,
1091
                "GridB" => 200,
1092
                "DrawSubTicks" => true,
1093
                "CycleBackground" => true,
1094
                'LabelRotation' => 10,
1095
            ];
1096
            $pChart->drawScale($scaleSettings);
1097
1098
            /* Draw the line chart */
1099
            $pChart->drawLineChart();
1100
            $pChart->drawPlotChart(
1101
                [
1102
                    "DisplayValues" => true,
1103
                    "PlotBorder" => true,
1104
                    "BorderSize" => 2,
1105
                    "Surrounding" => -60,
1106
                    "BorderAlpha" => 80,
1107
                ]
1108
            );
1109
1110
            /* Write the chart legend */
1111
            $pChart->drawLegend(
1112
                $xSize - 180,
1113
                9,
1114
                [
1115
                    "Style" => LEGEND_NOBORDER,
1116
                    "Mode" => LEGEND_HORIZONTAL,
1117
                    "FontR" => 0,
1118
                    "FontG" => 0,
1119
                    "FontB" => 0,
1120
                ]
1121
            );
1122
1123
            $cachePath = api_get_path(SYS_ARCHIVE_PATH);
1124
            $myCache = new pCache(['CacheFolder' => substr($cachePath, 0, strlen($cachePath) - 1)]);
1125
            $chartHash = $myCache->getHash($dataSet);
1126
1127
            $myCache->writeToCache($chartHash, $pChart);
1128
            $imgSysPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
1129
            $myCache->saveFromCache($chartHash, $imgSysPath);
1130
            $imgWebPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
1131
1132
            if (file_exists($imgSysPath)) {
1133
                $result = '<br /><div id="contentArea" style="text-align: center;" >';
1134
                $result .= '<img src="'.$imgWebPath.'" >';
1135
                $result .= '</div>';
1136
1137
                return $result;
1138
            }
1139
        }
1140
1141
        return '';
1142
    }
1143
1144
    /**
1145
     * @return array
1146
     */
1147
    private function getDataForGraph()
1148
    {
1149
        return $this->dataForGraph;
1150
    }
1151
1152
    /**
1153
     * @param $item
1154
     *
1155
     * @return mixed
1156
     */
1157
    private function build_certificate_min_score($item)
1158
    {
1159
        return $item->getCertificateMinScore();
1160
    }
1161
1162
    /**
1163
     * @param $item
1164
     *
1165
     * @return mixed
1166
     */
1167
    private function build_weight($item)
1168
    {
1169
        return $item->get_weight();
1170
    }
1171
1172
    /**
1173
     * @param $item
1174
     *
1175
     * @return mixed
1176
     */
1177
    private function build_course_code($item)
1178
    {
1179
        return $item->get_course_code();
1180
    }
1181
1182
    /**
1183
     * @param $item
1184
     *
1185
     * @return string
1186
     */
1187
    private function build_id_column($item)
1188
    {
1189
        switch ($item->get_item_type()) {
1190
            // category
1191
            case 'C':
1192
                return 'CATE'.$item->get_id();
1193
            // evaluation
1194
            case 'E':
1195
                return 'EVAL'.$item->get_id();
1196
            // link
1197
            case 'L':
1198
                return 'LINK'.$item->get_id();
1199
        }
1200
    }
1201
1202
    /**
1203
     * @param $item
1204
     * @param array $attributes
1205
     *
1206
     * @return string
1207
     */
1208
    private function build_type_column($item, $attributes = [])
1209
    {
1210
        return GradebookUtils::build_type_icon_tag($item->get_icon_name(), $attributes);
1211
    }
1212
1213
    /**
1214
     * Generate name column.
1215
     *
1216
     * @param GradebookItem $item
1217
     * @param string        $type simple|detail
1218
     *
1219
     * @return string
1220
     */
1221
    private function build_name_link($item, $type = 'detail', $spaces = 0)
1222
    {
1223
        $view = isset($_GET['view']) ? Security::remove_XSS($_GET['view']) : null;
1224
        $categoryId = $item->getCategory()->get_id();
1225
1226
        $cat = new Category();
1227
1228
        switch ($item->get_item_type()) {
1229
            case 'C':
1230
                // Category
1231
                $prms_uri = '?selectcat='.$item->get_id().'&view='.$view;
1232
                $isStudentView = api_is_student_view_active();
1233
                if (isset($is_student) || $isStudentView) {
1234
                    $prms_uri = $prms_uri.'&amp;isStudentView=studentview';
1235
                }
1236
                $show_message = $cat->show_message_resource_delete($item->get_course_code());
1237
1238
                return '&nbsp;<a href="'.Category::getUrl().$prms_uri.'">'
1239
                    .$item->get_name()
1240
                    .'</a>'
1241
                    .($item->is_course() ? ' &nbsp;['.$item->get_course_code().']'.$show_message : '');
1242
            case 'E':
1243
                // Evaluation
1244
                $course_id = CourseManager::get_course_by_category($categoryId);
1245
                $show_message = $cat->show_message_resource_delete($course_id);
1246
1247
                // course/platform admin can go to the view_results page
1248
                if (api_is_allowed_to_edit() && $show_message === false) {
1249
                    if ($item->get_type() == 'presence') {
1250
                        return '&nbsp;'
1251
                            .'<a href="gradebook_view_result.php?cidReq='.$course_id.'&amp;selecteval='.$item->get_id().'">'
1252
                            .$item->get_name()
1253
                            .'</a>';
1254
                    } else {
1255
                        $extra = Display::label(get_lang('Evaluation'));
1256
                        if ($type === 'simple') {
1257
                            $extra = '';
1258
                        }
1259
1260
                        return '&nbsp;'
1261
                            .'<a href="gradebook_view_result.php?'.api_get_cidreq().'&selecteval='.$item->get_id().'">'
1262
                            .$item->get_name()
1263
                            .'</a>&nbsp;'.$extra;
1264
                    }
1265
                } elseif (ScoreDisplay::instance()->is_custom() && $show_message === false) {
1266
                    // students can go to the statistics page (if custom display enabled)
1267
                    return '&nbsp;'
1268
                        .'<a href="gradebook_statistics.php?'.api_get_cidreq().'&selecteval='.$item->get_id().'">'
1269
                        .$item->get_name()
1270
                        .'</a>';
1271
                } elseif ($show_message === false && !api_is_allowed_to_edit() && !ScoreDisplay::instance()->is_custom()) {
1272
                    return '&nbsp;'
1273
                        .'<a href="gradebook_statistics.php?'.api_get_cidreq().'&selecteval='.$item->get_id().'">'
1274
                        .$item->get_name()
1275
                        .'</a>';
1276
                } else {
1277
                    return '['.get_lang('Evaluation').']&nbsp;&nbsp;'.$item->get_name().$show_message;
1278
                }
1279
                // no break because of return
1280
            case 'L':
1281
                // Link
1282
                $course_id = CourseManager::get_course_by_category($categoryId);
1283
                $show_message = $cat->show_message_resource_delete($course_id);
1284
1285
                $url = $item->get_link();
1286
                $text = $item->get_name();
1287
                if (isset($url) && false === $show_message) {
1288
                    $text = '&nbsp;<a href="'.$item->get_link().'">'
1289
                        .$item->get_name()
1290
                        .'</a>';
1291
                }
1292
1293
                $extra = Display::label($item->get_type_name(), 'info');
1294
                if ('simple' === $type) {
1295
                    $extra = '';
1296
                }
1297
                $extra .= $item->getSkillsFromItem();
1298
                $text .= "&nbsp;".$extra.$show_message;
1299
1300
                /*if ($item instanceof ExerciseLink) {
1301
                    $spaces = str_repeat('&nbsp;', $spaces);
1302
                    $text .= '<br /><br />'.$spaces.$item->getLpListToString();
1303
                }*/
1304
1305
                $cc = $this->currentcat->get_course_code();
1306
                if (empty($cc)) {
1307
                    $text .= '&nbsp;[<a href="'.api_get_path(REL_COURSE_PATH).$item->get_course_code().'/">'.$item->get_course_code().'</a>]';
1308
                }
1309
1310
                return $text;
1311
        }
1312
    }
1313
1314
    /**
1315
     * @param AbstractLink $item
1316
     *
1317
     * @return string|null
1318
     */
1319
    private function build_edit_column($item)
1320
    {
1321
        switch ($item->get_item_type()) {
1322
            case 'C':
1323
                // Category
1324
                return GradebookUtils::build_edit_icons_cat($item, $this->currentcat);
1325
            case 'E':
1326
                // Evaluation
1327
                return GradebookUtils::build_edit_icons_eval($item, $this->currentcat->get_id());
1328
            case 'L':
1329
                // Link
1330
                return GradebookUtils::build_edit_icons_link($item, $this->currentcat->get_id());
1331
        }
1332
    }
1333
}
1334