FlatViewTable::display_graph_by_resource()   F
last analyzed

Complexity

Conditions 26
Paths 2306

Size

Total Lines 231
Code Lines 148

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 26
eloc 148
nc 2306
nop 0
dl 0
loc 231
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
set_time_limit(0);
5
6
use CpChart\Cache as pCache;
7
use CpChart\Data as pData;
8
use CpChart\Image as pImage;
9
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
10
11
/**
12
 * Class FlatViewTable
13
 * Table to display flat view (all evaluations and links for all students).
14
 *
15
 * @author Stijn Konings
16
 * @author Bert Steppé  - (refactored, optimised)
17
 * @author Julio Montoya Armas - Gradebook Graphics
18
 */
19
class FlatViewTable extends SortableTable
20
{
21
    public $datagen;
22
    private $selectcat;
23
    private $limit_enabled;
24
    private $offset;
25
    private $mainCourseCategory;
26
27
    public function __construct(
28
        Category $selectcat,
29
        array $users = [],
30
        array $evals = [],
31
        array $links = [],
32
        bool $limit_enabled = false,
33
        int $offset = 0,
34
        array $addparams = [],
35
        ?Category $mainCourseCategory = null
36
    ) {
37
        parent:: __construct(
38
            'flatviewlist',
39
            null,
40
            null,
41
            api_is_western_name_order() ? 1 : 0
42
        );
43
44
        $this->selectcat = $selectcat;
45
        $this->datagen = new FlatViewDataGenerator(
46
            $users,
47
            $evals,
48
            $links,
49
            ['only_subcat' => $this->selectcat->get_id()],
50
            $mainCourseCategory
51
        );
52
53
        $this->limit_enabled = $limit_enabled;
54
        $this->offset = $offset;
55
        if (!empty($addparams)) {
56
            $this->set_additional_parameters($addparams);
57
        }
58
59
        // step 2: generate rows: students
60
        $this->datagen->category = $this->selectcat;
61
        $this->mainCourseCategory = $mainCourseCategory;
62
    }
63
64
    /**
65
     * @param bool $value
66
     */
67
    public function setLimitEnabled($value)
68
    {
69
        $this->limit_enabled = (bool) $value;
70
    }
71
72
    /**
73
     * @return Category
74
     */
75
    public function getMainCourseCategory()
76
    {
77
        return $this->mainCourseCategory;
78
    }
79
80
    /**
81
     * Display gradebook graphs.
82
     */
83
    public function display_graph_by_resource()
84
    {
85
        $headerName = $this->datagen->get_header_names();
86
        $total_users = $this->datagen->get_total_users_count();
87
        $customdisplays = ScoreDisplay::instance()->get_custom_score_display_settings();
88
89
        if (empty($customdisplays)) {
90
            echo get_lang('To view graph score rule must be enabled');
91
92
            return '';
93
        }
94
95
        $user_results = $this->datagen->get_data_to_graph2(false);
96
97
        if (empty($user_results) || empty($total_users)) {
98
            echo get_lang('No results found');
99
100
            return '';
101
        }
102
103
        // Removing first name
104
        array_shift($headerName);
105
        // Removing last name
106
        array_shift($headerName);
107
        // Removing username
108
        array_shift($headerName);
109
110
        $pre_result = [];
111
        foreach ($user_results as $result) {
112
            for ($i = 0; $i < count($headerName); $i++) {
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...
113
                if (isset($result[$i + 1])) {
114
                    $pre_result[$i + 3][] = $result[$i + 1];
115
                }
116
            }
117
        }
118
119
        $i = 0;
120
        $resource_list = [];
121
        $pre_result2 = [];
122
        foreach ($pre_result as $key => $res_array) {
123
            rsort($res_array);
124
            $pre_result2[] = $res_array;
125
        }
126
127
        //@todo when a display custom does not exist the order of the color does not match
128
        //filling all the answer that are not responded with 0
129
        rsort($customdisplays);
130
131
        if ($total_users > 0) {
132
            foreach ($pre_result2 as $key => $res_array) {
133
                $key_list = [];
134
                foreach ($res_array as $user_result) {
135
                    $userResult = isset($user_result[1]) ? $user_result[1] : null;
136
                    if (!isset($resource_list[$key][$userResult])) {
137
                        $resource_list[$key][$userResult] = 0;
138
                    }
139
                    $resource_list[$key][$userResult]++;
140
                    $key_list[] = $userResult;
141
                }
142
143
                foreach ($customdisplays as $display) {
144
                    if (!in_array($display['display'], $key_list)) {
145
                        $resource_list[$key][$display['display']] = 0;
146
                    }
147
                }
148
                $i++;
149
            }
150
        }
151
152
        //fixing $resource_list
153
        $max = 0;
154
        $new_list = [];
155
        foreach ($resource_list as $key => $value) {
156
            $new_value = [];
157
            foreach ($customdisplays as $item) {
158
                if ($value[$item['display']] > $max) {
159
                    $max = $value[$item['display']];
160
                }
161
                $new_value[$item['display']] = strip_tags($value[$item['display']]);
162
            }
163
            $new_list[] = $new_value;
164
        }
165
        $resource_list = $new_list;
166
        $i = 1;
167
        // Cache definition
168
        $cachePath = api_get_path(SYS_ARCHIVE_PATH) . 'chart/';
169
        if (!file_exists($cachePath)) {
170
            mkdir($cachePath, 0755, true);
171
        }
172
173
        if (!is_writable($cachePath)) {
174
            chmod($cachePath, 0755);
175
        }
176
177
        foreach ($resource_list as $key => $resource) {
178
            // Reverse array, otherwise we get highest values first
179
            $resource = array_reverse($resource, true);
180
181
            $dataSet = new pData();
182
            $dataSet->addPoints($resource, 'Serie');
183
            $dataSet->addPoints(array_keys($resource), 'Labels');
184
            $header = $headerName[$i - 1];
185
            if (is_array($header) && isset($header['header'])) {
186
                $header = $header['header'];
187
            }
188
            $header = strip_tags(api_html_entity_decode($header));
189
            $dataSet->setSerieDescription('Labels', $header);
190
            $dataSet->setAbscissa('Labels');
191
            $dataSet->setAbscissaName(get_lang('Skills ranking'));
192
            $dataSet->setAxisName(0, get_lang('Learners'));
193
            $palette = [
194
                '0' => ['R' => 186, 'G' => 206, 'B' => 151, 'Alpha' => 100],
195
                '1' => ['R' => 210, 'G' => 148, 'B' => 147, 'Alpha' => 100],
196
                '2' => ['R' => 148, 'G' => 170, 'B' => 208, 'Alpha' => 100],
197
                '3' => ['R' => 221, 'G' => 133, 'B' => 61, 'Alpha' => 100],
198
                '4' => ['R' => 65, 'G' => 153, 'B' => 176, 'Alpha' => 100],
199
                '5' => ['R' => 114, 'G' => 88, 'B' => 144, 'Alpha' => 100],
200
                '6' => ['R' => 138, 'G' => 166, 'B' => 78, 'Alpha' => 100],
201
                '7' => ['R' => 171, 'G' => 70, 'B' => 67, 'Alpha' => 100],
202
                '8' => ['R' => 69, 'G' => 115, 'B' => 168, 'Alpha' => 100],
203
            ];
204
            $myCache = new pCache(['CacheFolder' => substr($cachePath, 0, strlen($cachePath) - 1)]);
205
            $chartHash = $myCache->getHash($dataSet);
206
            if ($myCache->isInCache($chartHash)) {
207
                $imgPath = $cachePath.$chartHash;
208
                $myCache->saveFromCache($chartHash, $imgPath);
209
            } else {
210
                /* Create the pChart object */
211
                $widthSize = 480;
212
                $heightSize = 250;
213
                $myPicture = new pImage($widthSize, $heightSize, $dataSet);
214
215
                /* Turn of Antialiasing */
216
                $myPicture->Antialias = false;
217
218
                /* Add a border to the picture */
219
                $myPicture->drawRectangle(
220
                    0,
221
                    0,
222
                    $widthSize - 1,
223
                    $heightSize - 1,
224
                    [
225
                        'R' => 0,
226
                        'G' => 0,
227
                        'B' => 0,
228
                    ]
229
                );
230
231
                /* Set the default font */
232
                $myPicture->setFontProperties(
233
                    [
234
                        'FontName' => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
235
                        'FontSize' => 10,
236
                    ]
237
                );
238
                /* Write the chart title */
239
                $myPicture->drawText(
240
                    250,
241
                    30,
242
                    $header,
243
                    [
244
                        'FontSize' => 12,
245
                        'Align' => TEXT_ALIGN_BOTTOMMIDDLE,
0 ignored issues
show
Bug introduced by
The constant TEXT_ALIGN_BOTTOMMIDDLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
246
                    ]
247
                );
248
249
                /* Define the chart area */
250
                $myPicture->setGraphArea(50, 40, $widthSize - 20, $heightSize - 50);
251
252
                /* Draw the scale */
253
                $scaleSettings = [
254
                    'GridR' => 200,
255
                    'GridG' => 200,
256
                    'GridB' => 200,
257
                    'DrawSubTicks' => true,
258
                    'CycleBackground' => true,
259
                    'Mode' => SCALE_MODE_START0,
0 ignored issues
show
Bug introduced by
The constant SCALE_MODE_START0 was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
260
                ];
261
                $myPicture->drawScale($scaleSettings);
262
263
                /* Turn on shadow computing */
264
                $myPicture->setShadow(
265
                    true,
266
                    [
267
                        'X' => 1,
268
                        'Y' => 1,
269
                        'R' => 0,
270
                        'G' => 0,
271
                        'B' => 0,
272
                        'Alpha' => 10,
273
                    ]
274
                );
275
276
                /* Draw the chart */
277
                $myPicture->setShadow(
278
                    true,
279
                    [
280
                        'X' => 1,
281
                        'Y' => 1,
282
                        'R' => 0,
283
                        'G' => 0,
284
                        'B' => 0,
285
                        'Alpha' => 10,
286
                    ]
287
                );
288
                $settings = [
289
                    'OverrideColors' => $palette,
290
                    'Gradient' => false,
291
                    'GradientMode' => GRADIENT_SIMPLE,
0 ignored issues
show
Bug introduced by
The constant GRADIENT_SIMPLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
292
                    'DisplayPos' => LABEL_POS_TOP,
0 ignored issues
show
Bug introduced by
The constant LABEL_POS_TOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
293
                    'DisplayValues' => true,
294
                    'DisplayR' => 0,
295
                    'DisplayG' => 0,
296
                    'DisplayB' => 0,
297
                    'DisplayShadow' => true,
298
                    'Surrounding' => 10,
299
                ];
300
                $myPicture->drawBarChart($settings);
301
                /* Render the picture (choose the best way) */
302
303
                $myCache->writeToCache($chartHash, $myPicture);
304
                $imgPath = $cachePath.$chartHash;
305
                $myCache->saveFromCache($chartHash, $imgPath);
306
            }
307
            echo '<img src="data:image/png;base64,' . base64_encode(file_get_contents($imgPath)) . '" >';
308
            if (0 == $i % 2 && 0 != $i) {
309
                echo '<br /><br />';
310
            } else {
311
                echo '&nbsp;&nbsp;&nbsp;';
312
            }
313
            $i++;
314
        }
315
    }
316
317
    /**
318
     * Function used by SortableTable to get total number of items in the table.
319
     */
320
    public function get_total_number_of_items()
321
    {
322
        return $this->datagen->get_total_users_count();
323
    }
324
325
    /**
326
     * Function used by SortableTable to generate the data to display.
327
     */
328
    public function get_table_data(
329
        $from = 1,
330
        $perPage = null,
331
        $column = null,
332
        $direction = null,
333
        $sort = null
334
    ) {
335
        $is_western_name_order = api_is_western_name_order();
336
337
        // create page navigation if needed
338
        $totalitems = $this->datagen->get_total_items_count();
339
340
        if ($this->limit_enabled && $totalitems > GRADEBOOK_ITEM_LIMIT) {
341
            $selectlimit = GRADEBOOK_ITEM_LIMIT;
342
        } else {
343
            $selectlimit = $totalitems;
344
        }
345
346
        $header = null;
347
        if ($this->limit_enabled && $totalitems > GRADEBOOK_ITEM_LIMIT) {
348
            $header .= '<table style="width: 100%; text-align: right; margin-left: auto; margin-right: auto;" border="0" cellpadding="2">'
349
                .'<tbody>'
350
                .'<tr>';
351
352
            // previous X
353
            $header .= '<td style="width:100%;">';
354
            if ($this->offset >= GRADEBOOK_ITEM_LIMIT) {
355
                $header .= '<a href="'.api_get_self()
356
                    .'?selectcat='.Security::remove_XSS($_GET['selectcat'])
357
                    .'&offset='.(($this->offset) - GRADEBOOK_ITEM_LIMIT)
358
                    .(isset($_GET['search']) ? '&search='.Security::remove_XSS($_GET['search']) : '').'">'
359
                    .Display::getMdiIcon(
360
                        ActionIcon::PREVIOUS,
361
                        'ch-tool-icon',
362
                        null,
363
                        ICON_SIZE_MEDIUM,
364
                        get_lang('Previous page')
365
                    )
366
                    .'</a>';
367
            } else {
368
                $header .= Display::getMdiIcon(
369
                    ActionIcon::PREVIOUS,
370
                    'ch-tool-icon-disabled',
371
                    null,
372
                    ICON_SIZE_MEDIUM,
373
                    get_lang('Previous page')
374
                );
375
            }
376
            $header .= ' ';
377
            // next X
378
            $calcnext = (($this->offset + (2 * GRADEBOOK_ITEM_LIMIT)) > $totalitems) ?
379
                ($totalitems - (GRADEBOOK_ITEM_LIMIT + $this->offset)) : GRADEBOOK_ITEM_LIMIT;
380
381
            if ($calcnext > 0) {
382
                $header .= '<a href="'.api_get_self()
383
                    .'?selectcat='.Security::remove_XSS($_GET['selectcat'])
384
                    .'&offset='.($this->offset + GRADEBOOK_ITEM_LIMIT)
385
                    .(isset($_GET['search']) ? '&search='.Security::remove_XSS($_GET['search']) : '').'">'
386
                    .Display::getMdiIcon(ActionIcon::NEXT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Next page'))
387
                    .'</a>';
388
            } else {
389
                $header .= Display::getMdiIcon(
390
                    ActionIcon::NEXT,
391
                    'ch-tool-icon-disabled',
392
                    null,
393
                    ICON_SIZE_MEDIUM,
394
                    get_lang('Next page')
395
                );
396
            }
397
            $header .= '</td>';
398
            $header .= '</tbody></table>';
399
            echo $header;
400
        }
401
402
        // retrieve sorting type
403
        if ($is_western_name_order) {
404
            $users_sorting = (0 == $this->column ? FlatViewDataGenerator::FVDG_SORT_FIRSTNAME : FlatViewDataGenerator::FVDG_SORT_LASTNAME);
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->column of type integer|mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
405
        } else {
406
            $users_sorting = (0 == $this->column ? FlatViewDataGenerator::FVDG_SORT_LASTNAME : FlatViewDataGenerator::FVDG_SORT_FIRSTNAME);
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $this->column of type integer|mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
407
        }
408
409
        if ('DESC' === $this->direction) {
410
            $users_sorting |= FlatViewDataGenerator::FVDG_SORT_DESC;
411
        } else {
412
            $users_sorting |= FlatViewDataGenerator::FVDG_SORT_ASC;
413
        }
414
415
        // step 1: generate columns: evaluations and links
416
        $header_names = $this->datagen->get_header_names($this->offset, $selectlimit);
417
        $userRowSpan = false;
418
        foreach ($header_names as $item) {
419
            if (is_array($item)) {
420
                $userRowSpan = true;
421
                break;
422
            }
423
        }
424
425
        $thAttributes = '';
426
        if ($userRowSpan) {
427
            $thAttributes = 'rowspan=2';
428
        }
429
430
        $this->set_header(0, $header_names[0], true, $thAttributes);
431
        $this->set_header(1, $header_names[1], true, $thAttributes);
432
433
        $column = 2;
434
        $firstHeader = [];
435
        while ($column < count($header_names)) {
436
            $headerData = $header_names[$column];
437
438
            if (is_array($headerData)) {
439
                $countItems = count($headerData['items']);
440
441
                $this->set_header(
442
                    $column,
443
                    $headerData['header'],
444
                    false,
445
                    'colspan="'.$countItems.'"'
446
                );
447
448
                foreach ($headerData['items'] as $item) {
449
                    $firstHeader[] = '<span class="text-center">'.$item.'</span>';
450
                }
451
            } else {
452
                $this->set_header($column, $headerData, false, $thAttributes);
453
            }
454
            $column++;
455
        }
456
457
        $data_array = $this->datagen->get_data(
458
            $users_sorting,
459
            $from,
460
            $this->per_page,
461
            $this->offset,
462
            $selectlimit
463
        );
464
465
        $table_data = [];
466
467
        if (!empty($firstHeader)) {
468
            $table_data[] = $firstHeader;
469
        }
470
471
        $columnOffset = empty($this->datagen->params['show_official_code']) ? 0 : 1;
472
473
        foreach ($data_array as $user_row) {
474
            $user_id = $user_row[0];
475
            unset($user_row[0]);
476
            $userInfo = api_get_user_info($user_id);
477
            if ($is_western_name_order) {
478
                $user_row[1 + $columnOffset] = $this->build_name_link(
479
                    $user_id,
480
                    $userInfo['firstname']
481
                );
482
                $user_row[2 + $columnOffset] = $this->build_name_link(
483
                    $user_id,
484
                    $userInfo['lastname']
485
                );
486
            } else {
487
                $user_row[1 + $columnOffset] = $this->build_name_link(
488
                    $user_id,
489
                    $userInfo['lastname']
490
                );
491
                $user_row[2 + $columnOffset] = $this->build_name_link(
492
                    $user_id,
493
                    $userInfo['firstname']
494
                );
495
            }
496
            $user_row = array_values($user_row);
497
498
            $table_data[] = $user_row;
499
        }
500
501
        return $table_data;
502
    }
503
504
    /**
505
     * @param $userId
506
     * @param $name
507
     *
508
     * @return string
509
     */
510
    private function build_name_link($userId, $name)
511
    {
512
        return '<a href="user_stats.php?userid='.$userId.'&selectcat='.$this->selectcat->get_id().'&'.api_get_cidreq().'">'.$name.'</a>';
513
    }
514
}
515