Passed
Push — 1.10.x ( e22269...acc912 )
by
unknown
49:56
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
    protected function __constructor($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
158
        return $this->custom_display;
159
    }
160
161
    /**
162
     * If coloring is enabled, scores below this value will be displayed in red.
163
     * @return int color split value, in percent (or null if feature not enabled)
164
     */
165
    public function get_color_split_value()
166
    {
167
        return $this->color_split_value;
168
    }
169
170
    /**
171
     * Get current gradebook category id
172
     * @return int  Category id
173
     */
174
    private function get_current_gradebook_category_id()
175
    {
176
        $tbl_gradebook_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
177
        $curr_course_code = api_get_course_id();
178
        $curr_session_id = api_get_session_id();
179
180
        if (empty($curr_session_id)) {
181
            $session_condition = ' AND session_id is null ';
182
        } else {
183
            $session_condition = ' AND session_id = '.$curr_session_id;
184
        }
185
186
        $sql = 'SELECT id FROM '.$tbl_gradebook_category.'
187
                WHERE course_code = "'.$curr_course_code.'" '. $session_condition;
188
        $rs  = Database::query($sql);
189
        $category_id = 0;
190
        if (Database::num_rows($rs) > 0) {
191
            $row = Database::fetch_row($rs);
192
            $category_id = $row[0];
193
        }
194
195
        return $category_id;
196
    }
197
198
    /**
199
     * Update custom score display settings
200
     * @param array $displays 2-dimensional array - every sub array must have keys (score, display)
201
     * @param int   score color percent (optional)
202
     * @param int   gradebook category id (optional)
203
     */
204
    public function update_custom_score_display_settings($displays, $scorecolpercent = 0, $category_id = null)
205
    {
206
        $this->custom_display = $displays;
207
        $this->custom_display_conv = $this->convert_displays($this->custom_display);
208
209
        if (isset($category_id)) {
210
            $category_id = intval($category_id);
211
        } else {
212
            $category_id = $this->get_current_gradebook_category_id();
213
        }
214
215
        // remove previous settings
216
        $table = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
217
        $sql = 'DELETE FROM '.$table.' WHERE category_id = '.$category_id;
218
        Database::query($sql);
219
220
        // add new settings
221
        $count = 0;
222 View Code Duplication
        foreach ($displays as $display) {
223
            $params = [
224
                'score' => $display['score'],
225
                'display' => $display['display'],
226
                'category_id' => $category_id,
227
                'score_color_percent' => $scorecolpercent,
228
            ];
229
            Database::insert($table, $params);
230
231
            $count++;
232
        }
233
    }
234
235
    /**
236
     * @param int $category_id
237
     * @return bool
238
     */
239
    public function insert_defaults($category_id)
240
    {
241
        if (empty($category_id)) {
242
            return false;
243
        }
244
245
        //Get this from DB settings
246
        $display = array(
247
            50 => get_lang('GradebookFailed'),
248
            60 => get_lang('GradebookPoor'),
249
            70 => get_lang('GradebookFair'),
250
            80 => get_lang('GradebookGood'),
251
            90 => get_lang('GradebookOutstanding'),
252
            100 => get_lang('GradebookExcellent')
253
        );
254
255
        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
256 View Code Duplication
        foreach($display as $value => $text) {
257
            $params = array(
258
                'score' => $value,
259
                'display' => $text,
260
                'category_id' => $category_id,
261
                'score_color_percent' => 0,
262
            );
263
            Database::insert($tbl_display, $params);
264
        }
265
    }
266
267
    /**
268
     * @return int|null|string
269
     */
270
    public function get_number_decimals()
271
    {
272
        $number_decimals = api_get_setting('gradebook_number_decimals');
273
        if (!isset($number_decimals)) {
274
            $number_decimals = 0;
275
        }
276
277
        return $number_decimals;
278
    }
279
280
    /**
281
     * Formats a number depending of the number of decimals
282
     *
283
     * @param float $score
284
     * @return float the score formatted
285
     */
286
    public function format_score($score)
287
    {
288
        return floatval(number_format($score, $this->get_number_decimals()));
289
    }
290
291
    /**
292
     * Display a score according to the current settings
293
     * @param array $score data structure, as returned by the calc_score functions
294
     * @param int $type one of the following constants:
295
     * SCORE_DIV, SCORE_PERCENT, SCORE_DIV_PERCENT, SCORE_AVERAGE
296
     * (ignored for student's view if custom score display is enabled)
297
     * @param int $what one of the following constants:
298
     * SCORE_BOTH, SCORE_ONLY_DEFAULT, SCORE_ONLY_CUSTOM (default: SCORE_BOTH)
299
     * (only taken into account if custom score display is enabled and for course/platform admin)
300
     *
301
     * @return string
302
     */
303
    public function display_score(
304
        $score,
305
        $type = SCORE_DIV_PERCENT,
306
        $what = SCORE_BOTH,
307
        $no_color = false
308
    ) {
309
        $my_score = $score == 0 ? 1 : $score;
310
311
        if ($type == SCORE_BAR) {
312
            $percentage = $my_score[0]/$my_score[1]*100;
313
314
            return Display::bar_progress($percentage);
315
        }
316
317
        if ($type == SCORE_SIMPLE) {
318
            $simple_score = $this->format_score($my_score[0]);
319
            return $simple_score;
320
        }
321
322
        if ($this->custom_enabled && isset($this->custom_display_conv)) {
323
            $display = $this->display_default($my_score, $type);
324
        } else {
325
            // if no custom display set, use default display
326
            $display = $this->display_default($my_score, $type);
327
        }
328
329
        if ($this->coloring_enabled && $no_color == false) {
330
            $my_score_denom = isset($score[1]) && !empty($score[1]) ? $score[1] : 1;
331
            $scoreCleaned = isset($score[0]) ? $score[0] : 0;
332
            if (($scoreCleaned / $my_score_denom) < ($this->color_split_value / 100)) {
333
                $display = Display::tag('font', $display, array('color'=>'red'));
334
            }
335
        }
336
337
        return $display;
338
    }
339
340
    /**
341
     * @param $score
342
     * @param $type
343
     * @return float|string
344
     */
345
    private function display_default($score, $type)
346
    {
347
        switch ($type) {
348
            case SCORE_DIV :                            // X / Y
349
                return $this->display_as_div($score);
350
            case SCORE_PERCENT :                        // XX %
351
                return $this->display_as_percent($score);
352
            case SCORE_DIV_PERCENT :                    // X / Y (XX %)
353
                return $this->display_as_div($score).' (' . $this->display_as_percent($score) . ')';
354
            case SCORE_AVERAGE :                        // XX %
355
                return $this->display_as_percent($score);
356
            case SCORE_DECIMAL :                        // 0.50  (X/Y)
357
                return $this->display_as_decimal($score);
358
            case SCORE_DIV_PERCENT_WITH_CUSTOM :        // X / Y (XX %) - Good!
359
                $custom = $this->display_custom($score);
360
                if (!empty($custom)) {
361
                    $custom = ' - '.$custom;
362
                }
363
                return $this->display_as_div($score).' (' . $this->display_as_percent($score) . ')'.$custom;
364
            case SCORE_DIV_SIMPLE_WITH_CUSTOM :         // X - Good!
365
                $custom = $this->display_custom($score);
366
367
                if (!empty($custom)) {
368
                    $custom = ' - '.$custom;
369
                }
370
371
                return $this->display_simple_score($score).$custom;
372
                break;
373
            case SCORE_DIV_SIMPLE_WITH_CUSTOM_LETTERS:
374
                $custom = $this->display_custom($score);
375
                if (!empty($custom)) {
376
                    $custom = ' - '.$custom;
377
                }
378
                $score = $this->display_simple_score($score);
379
380
                //needs sudo apt-get install php5-intl
381
                if (class_exists('NumberFormatter')) {
382
                    $iso = api_get_language_isocode();
383
                    $f = new NumberFormatter($iso, NumberFormatter::SPELLOUT);
384
                    $letters = $f->format($score);
385
                    $letters = api_strtoupper($letters);
386
                    $letters = " ($letters) ";
387
                }
388
389
                return $score.$letters.$custom;
390
                break;
391
            case SCORE_CUSTOM:                          // Good!
392
                return $this->display_custom($score);
393
        }
394
    }
395
396
    /**
397
     * @param array $score
398
     * @return float|string
399
     */
400
    private function display_simple_score($score)
401
    {
402
        if (isset($score[0])) {
403
            return $this->format_score($score[0]);
404
        }
405
        return '';
406
    }
407
408
    /**
409
     * Returns "1" for array("100", "100");
410
     * @param array $score
411
     * @return float
412
     */
413
    private function display_as_decimal($score)
414
    {
415
        $score_denom = ($score[1]==0) ? 1 : $score[1];
416
417
        return $this->format_score($score[0]/$score_denom);
418
    }
419
420
    /**
421
     * Returns "100 %" for array("100", "100");
422
     */
423
    private function display_as_percent($score)
424
    {
425
        $score_denom = ($score[1]==0) ? 1 : $score[1];
426
427
        return $this->format_score($score[0]/$score_denom*100) . ' %';
428
    }
429
430
    /**
431
     * Returns 10.00 / 10.00 for array("100", "100");
432
     * @param array $score
433
     *
434
     * @return string
435
     */
436
    private function display_as_div($score)
437
    {
438
        if ($score == 1) {
439
            return '0 / 0';
440
        } else {
441
            $score[0] = isset($score[0]) ? $this->format_score($score[0]) : 0;
442
            $score[1] = isset($score[1]) ? $this->format_score($score[1]) : 0;
443
            return  $score[0] . ' / ' . $score[1];
444
        }
445
    }
446
447
    /**
448
     * Depends on the teacher's configuration of thresholds. i.e. [0 50] "Bad", [50:100] "Good"
449
     * @param array $score
450
     */
451
    private function display_custom($score)
452
    {
453
        $my_score_denom= ($score[1]==0) ? 1 : $score[1];
454
        $scaledscore = $score[0] / $my_score_denom;
455
        if ($this->upperlimit_included) {
456
            foreach ($this->custom_display_conv as $displayitem) {
457
                if ($scaledscore <= $displayitem['score']) {
458
                    return $displayitem['display'];
459
                }
460
            }
461
        } else {
462
            if (!empty($this->custom_display_conv)) {
463
                foreach ($this->custom_display_conv as $displayitem) {
464
                    if ($scaledscore < $displayitem['score'] || $displayitem['score'] == 1) {
465
                        return $displayitem['display'];
466
                    }
467
                }
468
            }
469
        }
470
    }
471
472
    /**
473
     * Get score color percent by category
474
     * @param   int Gradebook category id
475
     * @return  int Score
476
     */
477
    private function get_score_color_percent($category_id = null)
478
    {
479
        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
480
        if (isset($category_id)) {
481
            $category_id = intval($category_id);
482
        } else {
483
            $category_id = $this->get_current_gradebook_category_id();
484
        }
485
486
        $sql = 'SELECT score_color_percent FROM '.$tbl_display.'
487
                WHERE category_id = '.$category_id.'
488
                LIMIT 1';
489
        $result = Database::query($sql);
490
        $score = 0;
491
        if (Database::num_rows($result) > 0) {
492
            $row = Database::fetch_row($result);
493
            $score = $row[0];
494
        }
495
496
        return $score;
497
    }
498
499
    /**
500
     * Get current custom score display settings
501
     * @param   int     Gradebook category id
502
     * @return  array   2-dimensional array every element contains 3 subelements (id, score, display)
503
     */
504
    private function get_custom_displays($category_id = null)
505
    {
506
        $tbl_display = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_DISPLAY);
507
        if (isset($category_id)) {
508
            $category_id = intval($category_id);
509
        } else {
510
            $category_id = $this->get_current_gradebook_category_id();
511
        }
512
        $sql = 'SELECT * FROM '.$tbl_display.'
513
                WHERE category_id = '.$category_id.'
514
                ORDER BY score';
515
        $result = Database::query($sql);
516
517
        return Database::store_result($result,'ASSOC');
518
    }
519
520
    /**
521
     * Convert display settings to internally used values
522
     */
523
    private function convert_displays($custom_display)
524
    {
525
        if (isset($custom_display)) {
526
            // get highest score entry, and copy each element to a new array
527
            $converted = array();
528
            $highest = 0;
529
            foreach ($custom_display as $element) {
530
                if ($element['score'] > $highest) {
531
                    $highest = $element['score'];
532
                }
533
                $converted[] = $element;
534
            }
535
            // sort the new array (ascending)
536
            usort($converted, array('ScoreDisplay', 'sort_display'));
537
538
            // adjust each score in such a way that
539
            // each score is scaled between 0 and 1
540
            // the highest score in this array will be equal to 1
541
            $converted2 = array();
542
            foreach ($converted as $element) {
543
                $newelement = array();
544
                if (isset($highest) && !empty($highest) && $highest > 0) {
545
                    $newelement['score'] = $element['score'] / $highest;
546
                } else {
547
                    $newelement['score'] = 0;
548
                }
549
                $newelement['display'] = $element['display'];
550
                $converted2[] = $newelement;
551
            }
552
            return $converted2;
553
        } else {
554
            return null;
555
        }
556
    }
557
558
    /**
559
     * @param array $item1
560
     * @param array $item2
561
     * @return int
562
     */
563 View Code Duplication
    private function sort_display($item1, $item2)
564
    {
565
        if ($item1['score'] == $item2['score']) {
566
            return 0;
567
        } else {
568
            return ($item1['score'] < $item2['score'] ? -1 : 1);
569
        }
570
    }
571
}
572