Completed
Push — master ( 76311f...209ded )
by Nate
25:30 queued 10:27
created

ElementMetricCollection::resetScore()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
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
     * @inheritdoc
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
     * @inheritdoc
57
     */
58
    public function resetScore()
59
    {
60
        foreach ($this->getMetrics() as $metric) {
61
            $metric->resetScore();
62
        }
63
64
        return parent::resetScore();
65
    }
66
67
68
    /*******************************************
69
     * METRICS (CHILDREN)
70
     *******************************************/
71
72
    /**
73
     * @return MetricInterface[]
74
     */
75
    public function getMetrics(): array
76
    {
77
        if ($this->metrics === null) {
78
            $this->setMetrics(
79
                $this->loadMetrics()
80
            );
81
        }
82
83
        return $this->metrics;
84
    }
85
86
    /**
87
     * @return array
88
     */
89
    protected function loadMetrics(): array
90
    {
91
        if ($this->getIsNewRecord()) {
92
            return (array)static::METRICS;
93
        }
94
95
        return array_filter(array_merge(
96
            $this->children,
97
            (array)ArrayHelper::getValue($this->settings, 'metrics', [])
98
        ));
99
    }
100
101
    /**
102
     * @param array $metrics
103
     * @return $this
104
     */
105
    public function setMetrics(array $metrics = [])
106
    {
107
        $this->metrics = [];
108
109
        foreach ($metrics as $metric) {
110
            if (!$metric instanceof MetricInterface) {
111
                $metric = $this->createMetric($metric);
112
            }
113
114
            $this->metrics[] = $metric;
115
        }
116
117
        return $this;
118
    }
119
120
    /**
121
     * @noinspection PhpDocMissingThrowsInspection
122
     *
123
     * @param $metric
124
     * @return MetricInterface
125
     */
126
    protected function createMetric($metric): MetricInterface
127
    {
128
        if (is_string($metric)) {
129
            $metric = ['class' => $metric];
130
        }
131
132
        /** Pass along other vars */
133
        if (is_array($metric)) {
134
            if (!isset($metric['elementId'])) {
135
                $metric['element'] = $metric['element'] ?? $this->getElement();
136
            }
137
138
            $metric['dateCalculated'] = $metric['dateCalculated'] ?? $this->dateCalculated;
139
        }
140
141
        /** @noinspection PhpUnhandledExceptionInspection */
142
        /** @noinspection PhpIncompatibleReturnTypeInspection */
143
        return MetricHelper::create($metric);
144
    }
145
146
    /*******************************************
147
     * CHILDREN (RECORDS)
148
     *******************************************/
149
150
    /**
151
     * @return ElementMetricQuery
152
     */
153
    public function getChildren(): ElementMetricQuery
154
    {
155
        /** @var ElementMetricQuery $query */
156
        $query = $this->hasMany(
157
            static::class,
158
            ['parentId' => 'id']
159
        );
160
161
        // Prep query for children
162
        $query->class(null)
163
            ->parentId(':notempty:');
164
165
        return $query;
166
    }
167
168
    /*******************************************
169
     * VALIDATE (CHILD RECORDS)
170
     *******************************************/
171
172
    /**
173
     * @inheritdoc
174
     */
175
    public function beforeValidate()
176
    {
177
        $success = true;
178
        foreach ($this->getMetrics() as $metric) {
179
            if ($metric instanceof ElementMetric) {
180
                if (!$metric->validate()) {
181
                    $success = false;
182
                }
183
            }
184
        }
185
186
        return $success ? parent::beforeValidate() : false;
187
    }
188
189
    /*******************************************
190
     * SAVE (CHILD RECORDS)
191
     *******************************************/
192
193
    /**
194
     * @inheritdoc
195
     */
196
    public function beforeSave($insert)
197
    {
198
        /** @var array $metrics */
199
        $metrics = [];
200
201
        foreach ($this->getMetrics() as $metric) {
202
            if (!$metric instanceof ElementMetric) {
203
                $metrics[] = $metric->toConfig();
204
            }
205
        }
206
207
        // Merge into settings
208
        if (!empty($metrics)) {
209
            $this->settings = array_filter(array_merge(
210
                (array)$this->settings,
211
                [
212
                    'metrics' => $metrics
213
                ]
214
            ));
215
        }
216
217
        return parent::beforeSave($insert);
218
    }
219
220
    /**
221
     * @inheritdoc
222
     */
223
    public function afterSave($insert, $changedAttributes)
224
    {
225
        /** @var ElementMetric[] $metrics */
226
        $children = [];
227
228
        foreach ($this->getMetrics() as $metric) {
229
            if ($metric instanceof ElementMetric) {
230
                $children[] = $metric;
231
            }
232
        }
233
234
        if (!empty($children)) {
235
            $success = true;
236
            foreach ($children as $child) {
237
                $child->parentId = $this->id;
238
239
                if (!$child->save()) {
240
                    $success = false;
241
                }
242
            }
243
244
            if (!$success) {
245
                $this->addError('children', 'Unable to save children');
246
            }
247
        }
248
249
        return parent::afterSave($insert, $changedAttributes);
250
    }
251
}
252