Completed
Push — master ( b25c9d...3773b3 )
by Nate
23:52 queued 08:54
created

ElementMetricCollection   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 218
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 31
lcom 1
cbo 5
dl 0
loc 218
rs 9.92
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A calculateScore() 0 12 3
A getMetrics() 0 10 2
A loadMetrics() 0 11 2
A setMetrics() 0 14 3
A createMetric() 0 19 4
A getChildren() 0 14 1
A beforeValidate() 0 13 5
A beforeSave() 0 23 4
B afterSave() 0 28 7
1
<?php
2
3
/**
4
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 * @license    https://flipboxfactory.com/software/scorecard/license
6
 * @link       https://www.flipboxfactory.com/software/scorecard/
7
 */
8
9
namespace flipbox\craft\scorecard\records;
10
11
use flipbox\ember\helpers\ArrayHelper;
12
use flipbox\craft\scorecard\queries\ElementMetricQuery;
13
use flipbox\craft\scorecard\helpers\MetricHelper;
14
use flipbox\craft\scorecard\metrics\MetricInterface;
15
16
/**
17
 * @author Flipbox Factory <[email protected]>
18
 * @since 1.0.0
19
 *
20
 * @property ElementMetric[] $children
21
 */
22
abstract class ElementMetricCollection extends ElementMetric
23
{
24
    /**
25
     * @return array
26
     */
27
    const METRICS = [];
28
29
    /**
30
     * @var MetricInterface[]
31
     */
32
    private $metrics;
33
34
35
    /*******************************************
36
     * METRIC INTERFACE
37
     *******************************************/
38
39
    /**
40
     * @return float
41
     */
42
    protected function calculateScore(): float
43
    {
44
        // Sum of total/weight
45
        $total = $weights = 0;
46
47
        foreach ($this->getMetrics() as $metric) {
48
            $total += $metric->getScore();
49
            $weights += $metric->getWeight();
50
        }
51
52
        return $total > 0 ? (float)($total / $weights) : 0;
53
    }
54
55
56
    /*******************************************
57
     * METRICS (CHILDREN)
58
     *******************************************/
59
60
    /**
61
     * @return MetricInterface[]
62
     */
63
    public function getMetrics(): array
64
    {
65
        if ($this->metrics === null) {
66
            $this->setMetrics(
67
                $this->loadMetrics()
68
            );
69
        }
70
71
        return $this->metrics;
72
    }
73
74
    /**
75
     * @return array
76
     */
77
    protected function loadMetrics(): array
78
    {
79
        if ($this->getIsNewRecord()) {
80
            return (array)static::METRICS;
81
        }
82
83
        return array_filter(array_merge(
84
            $this->children,
85
            (array)ArrayHelper::getValue($this->settings, 'metrics', [])
86
        ));
87
    }
88
89
    /**
90
     * @param array $metrics
91
     * @return $this
92
     */
93
    public function setMetrics(array $metrics = [])
94
    {
95
        $this->metrics = [];
96
97
        foreach ($metrics as $metric) {
98
            if (!$metric instanceof MetricInterface) {
99
                $metric = $this->createMetric($metric);
100
            }
101
102
            $this->metrics[] = $metric;
103
        }
104
105
        return $this;
106
    }
107
108
    /**
109
     * @noinspection PhpDocMissingThrowsInspection
110
     *
111
     * @param $metric
112
     * @return MetricInterface
113
     */
114
    protected function createMetric($metric): MetricInterface
115
    {
116
        if (is_string($metric)) {
117
            $metric = ['class' => $metric];
118
        }
119
120
        /** Pass along other vars */
121
        if (is_array($metric)) {
122
            if (!isset($metric['elementId'])) {
123
                $metric['element'] = $metric['element'] ?? $this->getElement();
124
            }
125
126
            $metric['dateCalculated'] = $metric['dateCalculated'] ?? $this->dateCalculated;
127
        }
128
129
        /** @noinspection PhpUnhandledExceptionInspection */
130
        /** @noinspection PhpIncompatibleReturnTypeInspection */
131
        return MetricHelper::create($metric);
132
    }
133
134
    /*******************************************
135
     * CHILDREN (RECORDS)
136
     *******************************************/
137
138
    /**
139
     * @return ElementMetricQuery
140
     */
141
    public function getChildren(): ElementMetricQuery
142
    {
143
        /** @var ElementMetricQuery $query */
144
        $query = $this->hasMany(
145
            static::class,
146
            ['parentId' => 'id']
147
        );
148
149
        // Prep query for children
150
        $query->class(null)
151
            ->parentId(':notempty:');
152
153
        return $query;
154
    }
155
156
    /*******************************************
157
     * VALIDATE (CHILD RECORDS)
158
     *******************************************/
159
160
    /**
161
     * @inheritdoc
162
     */
163
    public function beforeValidate()
164
    {
165
        $success = true;
166
        foreach ($this->getMetrics() as $metric) {
167
            if ($metric instanceof ElementMetric) {
168
                if (!$metric->validate()) {
169
                    $success = false;
170
                }
171
            }
172
        }
173
174
        return $success ? parent::beforeValidate() : false;
175
    }
176
177
    /*******************************************
178
     * SAVE (CHILD RECORDS)
179
     *******************************************/
180
181
    /**
182
     * @inheritdoc
183
     */
184
    public function beforeSave($insert)
185
    {
186
        /** @var array $metrics */
187
        $metrics = [];
188
189
        foreach ($this->getMetrics() as $metric) {
190
            if (!$metric instanceof ElementMetric) {
191
                $metrics[] = $metric->toConfig();
192
            }
193
        }
194
195
        // Merge into settings
196
        if (!empty($metrics)) {
197
            $this->settings = array_filter(array_merge(
198
                (array)$this->settings,
199
                [
200
                    'metrics' => $metrics
201
                ]
202
            ));
203
        }
204
205
        return parent::beforeSave($insert);
206
    }
207
208
    /**
209
     * @inheritdoc
210
     */
211
    public function afterSave($insert, $changedAttributes)
212
    {
213
        /** @var ElementMetric[] $metrics */
214
        $children = [];
215
216
        foreach ($this->getMetrics() as $metric) {
217
            if ($metric instanceof ElementMetric) {
218
                $children[] = $metric;
219
            }
220
        }
221
222
        if (!empty($children)) {
223
            $success = true;
224
            foreach ($children as $child) {
225
                $child->parentId = $this->id;
226
227
                if (!$child->save()) {
228
                    $success = false;
229
                }
230
            }
231
232
            if (!$success) {
233
                $this->addError('children', 'Unable to save children');
234
            }
235
        }
236
237
        return parent::afterSave($insert, $changedAttributes);
238
    }
239
}
240