Aggregator::min()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace Cauditor;
4
5
/**
6
 * @author Matthias Mullie <[email protected]>
7
 * @copyright Copyright (c) 2016, Matthias Mullie. All rights reserved.
8
 * @license LICENSE MIT
9
 */
10
class Aggregator
11
{
12
    /**
13
     * @var array
14
     */
15
    protected $metrics;
16
17
    /**
18
     * @var float[][]
19
     */
20
    protected $flat;
21
22
    /**
23
     * @param array $metrics An AnalyzerInterface::execute result
24
     */
25
    public function __construct($metrics)
26
    {
27
        $this->metrics = $metrics;
28
    }
29
30
    /**
31
     * Get metric averages.
32
     *
33
     * @return float[]
34
     */
35
    public function average()
36
    {
37
        $flat = $this->flatten();
38
39
        $avg = array();
40
        foreach ($flat as $metric => $values) {
41
            $avg[$metric] = (float) number_format(array_sum($values) / count($values), 2, '.', '');
42
        }
43
44
        return $avg;
45
    }
46
47
    /**
48
     * Get metric minima.
49
     *
50
     * @return float[]
51
     */
52
    public function min()
53
    {
54
        $flat = $this->flatten();
55
56
        return array_map('min', $flat);
57
    }
58
59
    /**
60
     * Get metric maxima.
61
     *
62
     * @return float[]
63
     */
64
    public function max()
65
    {
66
        $flat = $this->flatten();
67
68
        return array_map('max', $flat);
69
    }
70
71
    /**
72
     * Get weighed metric averages, where the bigger a method/class is, the more
73
     * it's metric value will count towards the result.
74
     *
75
     * @return float[]
76
     */
77
    public function weigh()
78
    {
79
        $flat = $this->flatten();
80
81
        $weighed = array();
82
        foreach ($flat as $metric => $data) {
83
            $weighed[$metric] = 0;
84
            $relevant = 0;
85
            foreach ($data as $name => $value) {
86
                $loc = isset($flat['loc'][$name]) ? $flat['loc'][$name] : 0;
87
                $weighed[$metric] += $value * $loc;
88
                $relevant += $loc;
89
            }
90
91
            $weighed[$metric] = $weighed[$metric] / ($relevant ?: 1);
92
        }
93
94
        return $weighed;
95
    }
96
97
    /**
98
     * Flatten metrics into [metric => [value1, value1, value3]] array.
99
     *
100
     * @return float[][]
101
     */
102
    protected function flatten()
103
    {
104
        if (!$this->flat) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->flat of type double[][] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
105
            $this->flat = $this->recurse($this->metrics);
106
        }
107
108
        return $this->flat;
109
    }
110
111
    /**
112
     * @param array $metrics
113
     *
114
     * @return float[][]
115
     */
116
    protected function recurse(array $metrics)
117
    {
118
        $flat = array();
119
        $metrics = (array) $metrics;
120
121
        foreach ($metrics as $metric => $value) {
122
            // name & children are meta data, not metrics
123
            if (!in_array($metric, array('name', 'children'))) {
124
                $name = isset($metrics['name']) ? $metrics['name'] : '';
125
                $flat[$metric][$name] = $value;
126
            }
127
        }
128
129
        if (isset($metrics['children'])) {
130
            foreach ($metrics['children'] as $child) {
131
                $childTotals = $this->recurse($child);
132
                $flat = array_merge_recursive($flat, $childTotals);
133
            }
134
        }
135
136
        foreach ($flat as $metric => $data) {
137
            // array_merge_recursive will merge into an array of values if there
138
            // are multiple things with the same name, in which case we'll just
139
            // go with the last occurrence
140
            $flat[$metric] = array_map(function ($value) {
141
                return is_array($value) ? array_pop($value) : $value;
142
            }, $flat[$metric]);
143
        }
144
145
        return $flat;
146
    }
147
}
148