Passed
Push — 1.10.x ( acc912...021894 )
by
unknown
89:01 queued 37:44
created

ScoreDisplay::__constructor()   F

Complexity

Conditions 16
Paths 1176

Size

Total Lines 65
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 65
rs 2.7615
cc 16
eloc 37
nc 1176
nop 1

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
/**
5
 * Class ScoreDisplay
6
 * Display scores according to the settings made by the platform admin.
7
 * This class works as a singleton: call instance() to retrieve an object.
8
 * @author Bert Steppé
9
 * @package chamilo.gradebook
10
 */
11
class ScoreDisplay
12
{
13
    private $coloring_enabled;
14
    private $color_split_value;
15
    private $custom_enabled;
16
    private $upperlimit_included;
17
    private $custom_display;
18
    private $custom_display_conv;
19
20
    /**
21
     * Protected constructor - call instance() to instantiate
22
     */
23
    public function __construct($category_id = 0)
24
    {
25
        if (!empty($category_id)) {
26
            $this->category_id = $category_id;
27
        }
28
29
        // Loading portal settings + using standard functions.
30
31
        $value = api_get_setting('gradebook_score_display_coloring');
32
        $value = $value['my_display_coloring'];
33
34
        // Setting coloring.
35
        $this->coloring_enabled = $value == 'true' ? true : false;
36
37
        if ($this->coloring_enabled) {
38
            $value = api_get_setting('gradebook_score_display_colorsplit');
39
            if (isset($value)) {
40
                $this->color_split_value = $value;
41
            }
42
        }
43
44
        //Setting custom enabled
45
        $value = api_get_setting('gradebook_score_display_custom');
46
        $value = $value['my_display_custom'];
47
        $this->custom_enabled  = $value == 'true' ? true : false;
48
49
        if ($this->custom_enabled) {
50
            $params = array('category = ?' =>  array('Gradebook'));
51
            $displays = api_get_settings_params($params);
52
            $portal_displays = array();
53
            if (!empty($displays)) {
54
                foreach ($displays as $display) {
55
                    $data = explode('::', $display['selected_value']);
56
                    if (empty($data[1])) {
57
                        $data[1] = "";
58
                    }
59
                    $portal_displays[$data[0]] = array('score' => $data[0], 'display' => $data[1]);
60
                }
61
                sort($portal_displays);
62
            }
63
            $this->custom_display = $portal_displays;
64
            if (count($this->custom_display)>0) {
65
                $value = api_get_setting('gradebook_score_display_upperlimit');
66
                $value = $value['my_display_upperlimit'];
67
                $this->upperlimit_included  = $value == 'true' ? true : false;
68
                $this->custom_display_conv = $this->convert_displays($this->custom_display);
69
            }
70
        }
71
72
        //If teachers can override the portal parameters
73
74
        if (api_get_setting('teachers_can_change_score_settings') == 'true') {
75
            //Load course settings
76
            if ($this->custom_enabled) {
77
                $this->custom_display = $this->get_custom_displays();
78
                if (count($this->custom_display)> 0) {
79
                    $this->custom_display_conv = $this->convert_displays($this->custom_display);
80
                }
81
            }
82
83
            if ($this->coloring_enabled) {
84
                $this->color_split_value = $this->get_score_color_percent();
85
            }
86
        }
87
    }
88
89
    /**
90
     * Get the instance of this class
91
     * @param int $category_id
92
     */
93
    public static function instance($category_id = 0)
94
    {
95
        static $instance;
96
        if (!isset ($instance)) {
97
            $instance = new ScoreDisplay($category_id);
98
        }
99
100
        return $instance;
101
    }
102
103
    /**
104
     * Compare the custom display of 2 scores, can be useful in sorting
105
     */
106
    public static function compare_scores_by_custom_display ($score1, $score2)
107
    {
108
        if (!isset($score1)) {
109
            return (isset($score2) ? 1 : 0);
110
        } elseif (!isset($score2)) {
111
            return -1;
112
        } else {
113
            $scoredisplay = ScoreDisplay :: instance();
114
            $custom1 = $scoredisplay->display_custom($score1);
115
            $custom2 = $scoredisplay->display_custom($score2);
116 View Code Duplication
            if ($custom1 == $custom2) {
117
                return 0;
118
            } else {
119
                return (($score1[0]/$score1[1]) < ($score2[0]/$score2[1]) ? -1 : 1);
120
            }
121
        }
122
    }
123
124
125
126
    /**
127
     * Is coloring enabled ?
128
     */
129
    public function is_coloring_enabled()
130
    {
131
        return $this->coloring_enabled;
132
    }
133
134
    /**
135
     * Is custom score display enabled ?
136
     */
137
    public function is_custom()
138
    {
139
        return $this->custom_enabled;
140
    }
141
142
    /**
143
     * Is upperlimit included ?
144
     */
145
    public function is_upperlimit_included()
146
    {
147
        return $this->upperlimit_included;
148
    }
149
150
    /**
151
     * If custom score display is enabled, this will return the current settings.
152
     * See also update_custom_score_display_settings
153
     * @return array current settings (or null if feature not enabled)
154
     */
155
    public function get_custom_score_display_settings()
156
    {
157
        return $this->custom_display;
158
    }
159
160
    /**
161
     * If coloring is enabled, scores below this value will be displayed in red.
162
     * @return int color split value, in percent (or null if feature not enabled)
163
     */
164
    public function get_color_split_value()
165
    {
166
        return $this->color_split_value;
167
    }
168
169
    /**
170
     * Get current gradebook category id
171
     * @return int  Category id
172
     */
173
    private function get_current_gradebook_category_id()
174
    {
175
        $tbl_gradebook_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
176
        $curr_course_code = api_get_course_id();
177
        $curr_session_id = api_get_session_id();
178
179
        if (empty($curr_session_id)) {
180
            $session_condition = ' AND session_id is null ';
181
        } else {
182
            $session_condition = ' AND session_id = '.$curr_session_id;
183
        }
184
185
        $sql = 'SELECT id FROM '.$tbl_gradebook_category.'
186
                WHERE course_code = "'.$curr_course_code.'" '. $session_condition;
187
        $rs  = Database::query($sql);
188
        $category_id = 0;
189
        if (Database::num_rows($rs) > 0) {
190
            $row = Database::fetch_row($rs);
191
            $category_id = $row[0];
192
        }
193
194
        return $category_id;
195
    }
196
197
    /**
198
     * Update custom score display settings
199
     * @param array $displays 2-dimensional array - every sub array must have keys (score, display)
200
     * @param int   score color percent (optional)
201
     * @param int   gradebook category id (optional)
202
     */
203
    public function update_custom_score_display_settings($displays, $scorecolpercent = 0, $category_id = null)
204
    {
205
        $this->custom_display = $displays;
206
        $this->custom_display_conv = $this->convert_displays($this->custom_display);
207
208
        if (isset($category_id)) {
209
            $category_id = intval($category_id);
210
        } else {
211
            $category_id = $this->get_current_gradebook_category_id();
212
        }
213
214
        // remove previous settings
215
        $table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
216
        $sql = 'DELETE FROM '.$table.' WHERE category_id = '.$category_id;
217
        Database::query($sql);
218
219
        // add new settings
220
        $count = 0;
221 View Code Duplication
        foreach ($displays as $display) {
222
            $params = [
223
                'score' => $display['score'],
224
                'display' => $display['display'],
225
                'category_id' => $category_id,
226
                'score_color_percent' => $scorecolpercent,
227
            ];
228
            Database::insert($table, $params);
229
230
            $count++;
231
        }
232
    }
233
234
    /**
235
     * @param int $category_id
236
     * @return bool
237
     */
238
    public function insert_defaults($category_id)
239
    {
240
        if (empty($category_id)) {
241
            return false;
242
        }
243
244
        //Get this from DB settings
245
        $display = array(
246
            50 => get_lang('GradebookFailed'),
247
            60 => get_lang('GradebookPoor'),
248
            70 => get_lang('GradebookFair'),
249
            80 => get_lang('GradebookGood'),
250
            90 => get_lang('GradebookOutstanding'),
251
            100 => get_lang('GradebookExcellent')
252
        );
253
254
        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
255 View Code Duplication
        foreach($display as $value => $text) {
256
            $params = array(
257
                'score' => $value,
258
                'display' => $text,
259
                'category_id' => $category_id,
260
                'score_color_percent' => 0,
261
            );
262
            Database::insert($tbl_display, $params);
263
        }
264
    }
265
266
    /**
267
     * @return int|null|string
268
     */
269
    public function get_number_decimals()
270
    {
271
        $number_decimals = api_get_setting('gradebook_number_decimals');
272
        if (!isset($number_decimals)) {
273
            $number_decimals = 0;
274
        }
275
276
        return $number_decimals;
277
    }
278
279
    /**
280
     * Formats a number depending of the number of decimals
281
     *
282
     * @param float $score
283
     * @return float the score formatted
284
     */
285
    public function format_score($score)
286
    {
287
        return floatval(number_format($score, $this->get_number_decimals()));
288
    }
289
290
    /**
291
     * Display a score according to the current settings
292
     * @param array $score data structure, as returned by the calc_score functions
293
     * @param int $type one of the following constants:
294
     * SCORE_DIV, SCORE_PERCENT, SCORE_DIV_PERCENT, SCORE_AVERAGE
295
     * (ignored for student's view if custom score display is enabled)
296
     * @param int $what one of the following constants:
297
     * SCORE_BOTH, SCORE_ONLY_DEFAULT, SCORE_ONLY_CUSTOM (default: SCORE_BOTH)
298
     * (only taken into account if custom score display is enabled and for course/platform admin)
299
     *
300
     * @return string
301
     */
302
    public function display_score(
303
        $score,
304
        $type = SCORE_DIV_PERCENT,
305
        $what = SCORE_BOTH,
306
        $no_color = false
307
    ) {
308
        $my_score = $score == 0 ? 1 : $score;
309
310
        if ($type == SCORE_BAR) {
311
            $percentage = $my_score[0]/$my_score[1]*100;
312
313
            return Display::bar_progress($percentage);
314
        }
315
316
        if ($type == SCORE_SIMPLE) {
317
            $simple_score = $this->format_score($my_score[0]);
318
            return $simple_score;
319
        }
320
321
        if ($this->custom_enabled && isset($this->custom_display_conv)) {
322
            $display = $this->display_default($my_score, $type);
323
        } else {
324
            // if no custom display set, use default display
325
            $display = $this->display_default($my_score, $type);
326
        }
327
328
        if ($this->coloring_enabled && $no_color == false) {
329
            $my_score_denom = isset($score[1]) && !empty($score[1]) ? $score[1] : 1;
330
            $scoreCleaned = isset($score[0]) ? $score[0] : 0;
331
            if (($scoreCleaned / $my_score_denom) < ($this->color_split_value / 100)) {
332
                $display = Display::tag('font', $display, array('color'=>'red'));
333
            }
334
        }
335
336
        return $display;
337
    }
338
339
    /**
340
     * @param $score
341
     * @param $type
342
     * @return float|string
343
     */
344
    private function display_default($score, $type)
345
    {
346
        switch ($type) {
347
            case SCORE_DIV :                            // X / Y
348
                return $this->display_as_div($score);
349
            case SCORE_PERCENT :                        // XX %
350
                return $this->display_as_percent($score);
351
            case SCORE_DIV_PERCENT :                    // X / Y (XX %)
352
                return $this->display_as_div($score).' (' . $this->display_as_percent($score) . ')';
353
            case SCORE_AVERAGE :                        // XX %
354
                return $this->display_as_percent($score);
355
            case SCORE_DECIMAL :                        // 0.50  (X/Y)
356
                return $this->display_as_decimal($score);
357
            case SCORE_DIV_PERCENT_WITH_CUSTOM :        // X / Y (XX %) - Good!
358
                $custom = $this->display_custom($score);
359
                if (!empty($custom)) {
360
                    $custom = ' - '.$custom;
361
                }
362
                return $this->display_as_div($score).' (' . $this->display_as_percent($score) . ')'.$custom;
363
            case SCORE_DIV_SIMPLE_WITH_CUSTOM :         // X - Good!
364
                $custom = $this->display_custom($score);
365
366
                if (!empty($custom)) {
367
                    $custom = ' - '.$custom;
368
                }
369
370
                return $this->display_simple_score($score).$custom;
371
                break;
372
            case SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS:
373
                $custom = $this->display_custom($score);
374
                if (!empty($custom)) {
375
                    $custom = ' - '.$custom;
376
                }
377
                $score = $this->display_simple_score($score);
378
379
                //needs sudo apt-get install php5-intl
380
                if (class_exists('NumberFormatter')) {
381
                    $iso = api_get_language_isocode();
382
                    $f = new NumberFormatter($iso, NumberFormatter::SPELLOUT);
383
                    $letters = $f->format($score);
384
                    $letters = api_strtoupper($letters);
385
                    $letters = " ($letters) ";
386
                }
387
388
                return $score.$letters.$custom;
389
                break;
390
            case SCORE_CUSTOM:                          // Good!
391
                return $this->display_custom($score);
392
        }
393
    }
394
395
    /**
396
     * @param array $score
397
     * @return float|string
398
     */
399
    private function display_simple_score($score)
400
    {
401
        if (isset($score[0])) {
402
            return $this->format_score($score[0]);
403
        }
404
        return '';
405
    }
406
407
    /**
408
     * Returns "1" for array("100", "100");
409
     * @param array $score
410
     * @return float
411
     */
412
    private function display_as_decimal($score)
413
    {
414
        $score_denom = ($score[1]==0) ? 1 : $score[1];
415
416
        return $this->format_score($score[0]/$score_denom);
417
    }
418
419
    /**
420
     * Returns "100 %" for array("100", "100");
421
     */
422
    private function display_as_percent($score)
423
    {
424
        $score_denom = ($score[1]==0) ? 1 : $score[1];
425
426
        return $this->format_score($score[0]/$score_denom*100) . ' %';
427
    }
428
429
    /**
430
     * Returns 10.00 / 10.00 for array("100", "100");
431
     * @param array $score
432
     *
433
     * @return string
434
     */
435
    private function display_as_div($score)
436
    {
437
        if ($score == 1) {
438
            return '0 / 0';
439
        } else {
440
            $score[0] = isset($score[0]) ? $this->format_score($score[0]) : 0;
441
            $score[1] = isset($score[1]) ? $this->format_score($score[1]) : 0;
442
            return  $score[0] . ' / ' . $score[1];
443
        }
444
    }
445
446
    /**
447
     * Depends on the teacher's configuration of thresholds. i.e. [0 50] "Bad", [50:100] "Good"
448
     * @param array $score
449
     */
450
    private function display_custom($score)
451
    {
452
        $my_score_denom= ($score[1]==0) ? 1 : $score[1];
453
        $scaledscore = $score[0] / $my_score_denom;
454
        if ($this->upperlimit_included) {
455
            foreach ($this->custom_display_conv as $displayitem) {
456
                if ($scaledscore <= $displayitem['score']) {
457
                    return $displayitem['display'];
458
                }
459
            }
460
        } else {
461
            if (!empty($this->custom_display_conv)) {
462
                foreach ($this->custom_display_conv as $displayitem) {
463
                    if ($scaledscore < $displayitem['score'] || $displayitem['score'] == 1) {
464
                        return $displayitem['display'];
465
                    }
466
                }
467
            }
468
        }
469
    }
470
471
    /**
472
     * Get score color percent by category
473
     * @param   int Gradebook category id
474
     * @return  int Score
475
     */
476
    private function get_score_color_percent($category_id = null)
477
    {
478
        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
479
        if (isset($category_id)) {
480
            $category_id = intval($category_id);
481
        } else {
482
            $category_id = $this->get_current_gradebook_category_id();
483
        }
484
485
        $sql = 'SELECT score_color_percent FROM '.$tbl_display.'
486
                WHERE category_id = '.$category_id.'
487
                LIMIT 1';
488
        $result = Database::query($sql);
489
        $score = 0;
490
        if (Database::num_rows($result) > 0) {
491
            $row = Database::fetch_row($result);
492
            $score = $row[0];
493
        }
494
495
        return $score;
496
    }
497
498
    /**
499
     * Get current custom score display settings
500
     * @param   int     Gradebook category id
501
     * @return  array   2-dimensional array every element contains 3 subelements (id, score, display)
502
     */
503
    private function get_custom_displays($category_id = null)
504
    {
505
        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
506
        if (isset($category_id)) {
507
            $category_id = intval($category_id);
508
        } else {
509
            $category_id = $this->get_current_gradebook_category_id();
510
        }
511
        $sql = 'SELECT * FROM '.$tbl_display.'
512
                WHERE category_id = '.$category_id.'
513
                ORDER BY score';
514
        $result = Database::query($sql);
515
516
        return Database::store_result($result,'ASSOC');
517
    }
518
519
    /**
520
     * Convert display settings to internally used values
521
     */
522
    private function convert_displays($custom_display)
523
    {
524
        if (isset($custom_display)) {
525
            // get highest score entry, and copy each element to a new array
526
            $converted = array();
527
            $highest = 0;
528
            foreach ($custom_display as $element) {
529
                if ($element['score'] > $highest) {
530
                    $highest = $element['score'];
531
                }
532
                $converted[] = $element;
533
            }
534
            // sort the new array (ascending)
535
            usort($converted, array('ScoreDisplay', 'sort_display'));
536
537
            // adjust each score in such a way that
538
            // each score is scaled between 0 and 1
539
            // the highest score in this array will be equal to 1
540
            $converted2 = array();
541
            foreach ($converted as $element) {
542
                $newelement = array();
543
                if (isset($highest) && !empty($highest) && $highest > 0) {
544
                    $newelement['score'] = $element['score'] / $highest;
545
                } else {
546
                    $newelement['score'] = 0;
547
                }
548
                $newelement['display'] = $element['display'];
549
                $converted2[] = $newelement;
550
            }
551
            return $converted2;
552
        } else {
553
            return null;
554
        }
555
    }
556
557
    /**
558
     * @param array $item1
559
     * @param array $item2
560
     * @return int
561
     */
562 View Code Duplication
    private function sort_display($item1, $item2)
563
    {
564
        if ($item1['score'] === $item2['score']) {
565
566
            return 0;
567
        } else {
568
            return ($item1['score'] < $item2['score'] ? -1 : 1);
569
        }
570
    }
571
}
572