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

ElementMetric::resetScore()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
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 Craft;
12
use craft\helpers\DateTimeHelper;
13
use craft\helpers\StringHelper;
14
use flipbox\ember\helpers\ModelHelper;
15
use flipbox\ember\records\ActiveRecordWithId;
16
use flipbox\ember\records\traits\ElementAttribute;
17
use flipbox\craft\scorecard\queries\ElementMetricQuery;
18
use flipbox\craft\scorecard\helpers\MetricHelper;
19
use flipbox\craft\scorecard\metrics\SavableMetricInterface;
20
use flipbox\craft\scorecard\validators\ElementMetricValidator;
21
22
/**
23
 * @author Flipbox Factory <[email protected]>
24
 * @since 1.0.0
25
 *
26
 * @property int $parentId
27
 * @property string $class
28
 * @property float $score
29
 * @property float $weight
30
 * @property string $version
31
 * @property array|null $settings
32
 * @property \DateTime $dateCalculated
33
 */
34
abstract class ElementMetric extends ActiveRecordWithId implements SavableMetricInterface
35
{
36
    use ElementAttribute;
37
38
    /**
39
     * The default score weight
40
     */
41
    const WEIGHT = 1;
42
43
    /**
44
     * The default metric version
45
     */
46
    const VERSION = '1.0';
47
48
    /**
49
     * The table alias
50
     */
51
    const TABLE_ALIAS = 'scorecard_element_metrics';
52
53
    /**
54
     * The Active Query class
55
     */
56
    const ACTIVE_QUERY_CLASS = ElementMetricQuery::class;
57
58
    /**
59
     * @inheritdoc
60
     */
61
    protected $getterPriorityAttributes = ['elementId', 'score', 'dateCalculated'];
62
63
    /**
64
     * @return float
65
     */
66
    abstract protected function calculateScore(): float;
67
68
    /**
69
     * @inheritdoc
70
     */
71
    public function init()
72
    {
73
        parent::init();
74
75
        $this->setAttribute(
76
            'settings',
77
            MetricHelper::resolveSettings(
78
                $this->getAttribute('settings')
79
            )
80
        );
81
82
        // Always this class
83
        $this->class = static::class;
84
85
        // Defaults
86
        if ($this->getIsNewRecord()) {
87
            $this->weight = $this->weight ?: static::WEIGHT;
88
            $this->version = $this->version ?: static::VERSION;
89
            $this->dateCalculated = $this->dateCalculated ?: DateTimeHelper::currentUTCDateTime();
90
        }
91
    }
92
93
    /**
94
     * @inheritdoc
95
     */
96
    public static function find()
97
    {
98
        /** @noinspection PhpUnhandledExceptionInspection */
99
        /** @noinspection PhpIncompatibleReturnTypeInspection */
100
        return Craft::createObject(
101
            static::ACTIVE_QUERY_CLASS,
102
            [
103
                get_called_class(),
104
                [
105
                    'class' => static::class
106
                ]
107
            ]
108
        );
109
    }
110
111
    /**
112
     * @inheritdoc
113
     */
114
    public function resetScore()
115
    {
116
        $this->setAttribute('score', null);
117
        return $this;
118
    }
119
120
    /**
121
     * @inheritdoc
122
     */
123
    public function beforeSave($insert)
124
    {
125
        // Make sure score is calculated
126
        $this->getScore();
127
128
        return parent::beforeSave($insert);
129
    }
130
131
    /**
132
     * @inheritdoc
133
     */
134
    public static function instantiate($row)
135
    {
136
        $class = $row['class'] ?? static::class;
137
        return new $class;
138
    }
139
140
    /**
141
     * @inheritdoc
142
     */
143
    public function rules()
144
    {
145
        return array_merge(
146
            parent::rules(),
147
            $this->elementRules(),
148
            [
149
                [
150
                    [
151
                        'class'
152
                    ],
153
                    ElementMetricValidator::class
154
                ],
155
                [
156
                    [
157
                        'parentId',
158
                    ],
159
                    'number',
160
                    'integerOnly' => true
161
                ],
162
                [
163
                    [
164
                        'score',
165
                        'weight',
166
                    ],
167
                    'number'
168
                ],
169
                [
170
                    [
171
                        'elementId',
172
                        'class',
173
                        'weight',
174
                        'version',
175
                    ],
176
                    'required'
177
                ],
178
                [
179
                    [
180
                        'class',
181
                        'settings',
182
                        'score',
183
                        'weight',
184
                        'version',
185
                        'dateCalculated'
186
                    ],
187
                    'safe',
188
                    'on' => [
189
                        ModelHelper::SCENARIO_DEFAULT
190
                    ]
191
                ]
192
            ]
193
        );
194
    }
195
196
197
    /*******************************************
198
     * METRIC INTERFACE
199
     *******************************************/
200
201
    /**
202
     * @inheritdoc
203
     * @throws \ReflectionException
204
     */
205
    public static function displayName(): string
206
    {
207
        return StringHelper::titleize(
208
            (new \ReflectionClass(static::class))
209
                ->getShortName()
210
        );
211
    }
212
213
    /**
214
     * @inheritdoc
215
     */
216
    public function getWeight(): float
217
    {
218
        return (float)$this->getAttribute('weight');
219
    }
220
221
    /**
222
     * @inheritdoc
223
     */
224
    public function getVersion(): string
225
    {
226
        return (string)$this->getAttribute('version');
227
    }
228
229
    /**
230
     * @inheritdoc
231
     */
232
    public function getScore(): float
233
    {
234
        if ($this->getAttribute('score') === null) {
235
            $this->setAttribute('score', $this->calculateScore() * $this->getWeight());
236
        }
237
238
        return (float)$this->getAttribute('score');
239
    }
240
241
    /**
242
     * @return \DateTime|null
243
     */
244
    public function getDateCalculated()
245
    {
246
        $dateCalculated = $this->getAttribute('dateCalculated');
247
248
        if ($dateCalculated !== null && !$dateCalculated instanceof \DateTime) {
249
            if (is_array($dateCalculated)) {
250
                $dateCalculated = $dateCalculated['date'] ?? $dateCalculated;
251
            }
252
253
            $dateCalculated = DateTimeHelper::toDateTime($dateCalculated);
254
255
            $this->setAttribute('dateCalculated', $dateCalculated);
256
        }
257
258
        return $dateCalculated;
259
    }
260
261
262
    /*******************************************
263
     * SETTINGS
264
     *******************************************/
265
266
    /**
267
     * @param string $attribute
268
     * @return mixed
269
     */
270
    public function getSettingsValue(string $attribute)
271
    {
272
        $settings = MetricHelper::resolveSettings(
273
            $this->getAttribute('settings')
274
        );
275
276
        return $settings[$attribute] ?? null;
277
    }
278
279
    /**
280
     * @param string $attribute
281
     * @param $value
282
     * @return $this
283
     */
284
    public function setSettingsValue(string $attribute, $value)
285
    {
286
        $settings = MetricHelper::resolveSettings(
287
            $this->getAttribute('settings')
288
        );
289
        $settings[$attribute] = $value;
290
        $this->setAttribute('settings', $settings);
291
292
        return $this;
293
    }
294
295
296
    /*******************************************
297
     * CONFIGURATION
298
     *******************************************/
299
300
    /**
301
     * @return array
302
     */
303
    public function toConfig(): array
304
    {
305
        return $this->toArray();
306
    }
307
}
308