Pivot   B
last analyzed

Complexity

Total Complexity 47

Size/Duplication

Total Lines 310
Duplicated Lines 13.55 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 90.15%

Importance

Changes 0
Metric Value
wmc 47
lcom 1
cbo 7
dl 42
loc 310
ccs 119
cts 132
cp 0.9015
rs 8.439
c 0
b 0
f 0

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A __clone() 0 13 4
A setSource() 0 7 2
A getSource() 0 4 1
A getInfo() 0 10 3
A setInfo() 0 9 3
A clearSelectors() 0 7 1
A clearSelectorRows() 0 4 1
A clearFilters() 0 4 1
A clearAggregates() 0 4 1
A clearSelectorColumns() 0 4 1
A clearInfo() 0 9 1
A reset() 0 6 1
A addSourceField() 0 4 1
A addFilter() 0 7 2
A addColumn() 9 9 3
A addRow() 9 9 3
A addAggregate() 0 14 2
A getSourceFields() 0 4 1
A getCurrentFilters() 0 8 2
A getCurrentColumns() 12 12 2
A getCurrentRows() 12 12 2
A hasColumns() 0 4 1
A hasRows() 0 4 1
A getCurrentAggregates() 0 4 1
A getFieldElement() 0 7 2
A getFieldsCollection() 0 4 1
A getAggregatesCollection() 0 4 1
A getFiltersCollection() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Pivot often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Pivot, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace EngineWorks\Pivot;
3
4
class Pivot
5
{
6
    /**
7
     * Table name, View name or SELECT instruction to extract the values
8
     * @var string
9
     */
10
    private $source;
11
12
    /**
13
     * Collection of all fields used in the source
14
     * @var Fields|Field[]
15
     */
16
    private $fields;
17
18
    /**
19
     * Collection of rules
20
     * @var Filters|Filter[]
21
     */
22
    private $filters;
23
24
    /**
25
     * Collection of columns
26
     * @var array
27
     */
28
    private $columns;
29
30
    /**
31
     * Collection of rows
32
     * @var array
33
     */
34
    private $rows;
35
36
    /**
37
     * Collection of aggregates
38
     * @var Aggregates|Aggregate[]
39
     */
40
    private $aggregates;
41
42
    /**
43
     * Information of extended information
44
     * @var array $info
45
     */
46
    private $info;
47
48 18
    public function __construct($source = '')
49
    {
50 18
        $this->fields = new Fields();
51 18
        $this->aggregates = new Aggregates();
52 18
        $this->filters = new Filters();
53 18
        $this->rows = [];
54 18
        $this->columns = [];
55 18
        $this->info = [];
56 18
        $this->clearInfo();
57 18
        $this->setSource($source);
58 18
    }
59
60 5
    public function __clone()
61
    {
62
        // Force a copy of this->object, otherwise  it will point to same object.
63 5
        if (null !== $this->fields) {
64 5
            $this->fields = clone $this->fields;
65
        }
66 5
        if (null !== $this->filters) {
67 5
            $this->filters = clone $this->filters;
68
        }
69 5
        if (null !== $this->aggregates) {
70 5
            $this->aggregates = clone $this->aggregates;
71
        }
72 5
    }
73
74
    /**
75
     * @param string $source
76
     *
77
     * @throws PivotException If the source is not a string
78
     */
79 18
    public function setSource($source)
80
    {
81 18
        if (! is_string($source)) {
82
            throw new PivotException('A source string must be provided');
83
        }
84 18
        $this->source = (string) $source;
85 18
    }
86
87
    /**
88
     * @return string
89
     */
90 13
    public function getSource()
91
    {
92 13
        return $this->source;
93
    }
94
95
    /**
96
     * Return a current value of information
97
     * If keyword not found return FALSE
98
     * If no keyword provided then it returns the complete array of values
99
     *
100
     * @param string $keyword
101
     * @return mixed
102
     */
103 3
    public function getInfo($keyword = '')
104
    {
105 3
        if (! $keyword) {
106
            return $this->info;
107
        }
108 3
        if (array_key_exists($keyword, $this->info)) {
109 3
            return $this->info[$keyword];
110
        }
111
        return false;
112
    }
113
114
    /**
115
     * @param string $keyword
116
     * @param mixed $value
117
     * @throws PivotException
118
     */
119 5
    public function setInfo($keyword, $value)
120
    {
121 5
        if (! is_string($keyword)) {
122
            throw new PivotException('A keyword string must be provided');
123
        }
124 5
        if (array_key_exists($keyword, $this->info)) {
125 5
            $this->info[$keyword] = (string) $value;
126
        }
127 5
    }
128
129 11
    public function clearSelectors()
130
    {
131 11
        $this->clearSelectorRows();
132 11
        $this->clearSelectorColumns();
133 11
        $this->clearFilters();
134 11
        $this->clearAggregates();
135 11
    }
136
137 11
    public function clearSelectorRows()
138
    {
139 11
        $this->rows = [];
140 11
    }
141
142 11
    public function clearFilters()
143
    {
144 11
        $this->filters->clear();
145 11
    }
146
147 11
    public function clearAggregates()
148
    {
149 11
        $this->aggregates->clear();
150 11
    }
151
152 11
    public function clearSelectorColumns()
153
    {
154 11
        $this->columns = [];
155 11
    }
156
157 18
    public function clearInfo()
158
    {
159 18
        $this->info = [
160 18
            'author' => '',
161 18
            'created' => date('Y-m-d H:i:s', time()),
162 18
            'description' => '',
163 18
            'protected' => 'no',
164
        ];
165 18
    }
166
167 11
    public function reset()
168
    {
169 11
        $this->clearInfo();
170 11
        $this->fields->clear();
171 11
        $this->clearSelectors();
172 11
    }
173
174 13
    public function addSourceField($fieldname, $caption, $type)
175
    {
176 13
        $this->fields->addItem(new Field($fieldname, $caption, $type));
177 13
    }
178
179 6
    public function addFilter($fieldname, $operator, $arguments)
180
    {
181 6
        if (! $this->fields->exists($fieldname)) {
182
            throw new PivotException("Field $fieldname does not exists");
183
        }
184 6
        $this->filters->addItem(new Filter($fieldname, $operator, $arguments));
185 6
    }
186
187 8 View Code Duplication
    public function addColumn($fieldname)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
188
    {
189 8
        if (! $this->fields->exists($fieldname)) {
190
            throw new PivotException("Invalid field name $fieldname");
191
        }
192 8
        if (! in_array($fieldname, $this->columns)) {
193 8
            $this->columns[] = $fieldname;
194
        }
195 8
    }
196
197 11 View Code Duplication
    public function addRow($fieldname)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
198
    {
199 11
        if (! $this->fields->exists($fieldname)) {
200
            throw new PivotException("Invalid field name $fieldname");
201
        }
202 11
        if (! in_array($fieldname, $this->rows)) {
203 11
            $this->rows[] = $fieldname;
204
        }
205 11
    }
206
207
    /**
208
     * @param string $fieldname
209
     * @param string $asname
210
     * @param string $caption
211
     * @param string $agregatorfunction
212
     * @param int $decimals
213
     * @param string $order
214
     */
215 12
    public function addAggregate(
216
        $fieldname,
217
        $asname,
218
        $caption,
219
        $agregatorfunction,
220
        $decimals = 2,
221
        $order = Aggregate::ORDERNONE
222
    ) {
223 12
        static $counter = 0;
224 12
        if ('' === $asname) {
225
            $asname = '__agregator_' . (++$counter);
226
        }
227 12
        $this->aggregates->addItem(new Aggregate($fieldname, $asname, $caption, $agregatorfunction, $decimals, $order));
228 12
    }
229
230 4
    public function getSourceFields()
231
    {
232 4
        return $this->fields->asArray();
233
    }
234
235 2
    public function getCurrentFilters()
236
    {
237 2
        $return = $this->filters->asArray();
238 2
        foreach ($return as $i => $value) {
239 1
            $return[$i]['caption'] = $this->getFieldElement($value['fieldname'])->getCaption();
240
        }
241 2
        return $return;
242
    }
243
244 11 View Code Duplication
    public function getCurrentColumns()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
    {
246 11
        $return = [];
247 11
        foreach ($this->columns as $column) {
248 7
            $field = $this->getFieldElement($column);
249 7
            $return[] = [
250 7
                'caption' => $field->getCaption(),
251 7
                'fieldname' => $field->getFieldname(),
252
            ];
253
        }
254 11
        return $return;
255
    }
256
257 12 View Code Duplication
    public function getCurrentRows()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
258
    {
259 12
        $return = [];
260 12
        foreach ($this->rows as $row) {
261 10
            $field = $this->getFieldElement($row);
262 10
            $return[] = [
263 10
                'caption' => $field->getCaption(),
264 10
                'fieldname' => $field->getFieldname(),
265
            ];
266
        }
267 12
        return $return;
268
    }
269
270 9
    public function hasColumns()
271
    {
272 9
        return count($this->columns) > 0;
273
    }
274
275
    public function hasRows()
276
    {
277
        return count($this->rows) > 0;
278
    }
279
280 11
    public function getCurrentAggregates()
281
    {
282 11
        return $this->aggregates->asArray();
283
    }
284
285
    /**
286
     * Return an field object from the field list
287
     * @param string $fieldname
288
     * @return Field
289
     * @throws PivotException when field name does not exists
290
     */
291 10
    public function getFieldElement($fieldname)
292
    {
293 10
        if (! $this->fields->exists($fieldname)) {
294
            throw new PivotException("Expected to find field $fieldname but it does not exists in the list");
295
        }
296 10
        return $this->fields->value($fieldname);
297
    }
298
299
    public function getFieldsCollection()
300
    {
301
        return $this->fields;
302
    }
303
304 10
    public function getAggregatesCollection()
305
    {
306 10
        return $this->aggregates;
307
    }
308
309 9
    public function getFiltersCollection()
310
    {
311 9
        return $this->filters;
312
    }
313
}
314