Completed
Push — master ( c49581...65a2b8 )
by Nate
29:31 queued 14:35
created

ElementMetric::defaultDateCalculated()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
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 DateTime;
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 static function populateRecord($record, $row)
72
    {
73
        parent::populateRecord($record, $row);
74
75
        $record->version = static::VERSION;
76
        $record->weight = static::WEIGHT;
77
        $record->class = static::class;
78
    }
79
80
    /**
81
     * @inheritdoc
82
     * @throws \yii\base\InvalidConfigException
83
     * @return ElementMetricQuery
84
     */
85
    public static function find()
86
    {
87
        /** @noinspection PhpUnhandledExceptionInspection */
88
        /** @noinspection PhpIncompatibleReturnTypeInspection */
89
        return Craft::createObject(
90
            static::ACTIVE_QUERY_CLASS,
91
            [
92
                get_called_class(),
93
                [
94
                    'class' => static::class
95
                ]
96
            ]
97
        );
98
    }
99
100
    /**
101
     * @inheritdoc
102
     */
103
    public function resetScore()
104
    {
105
        $this->setAttribute('score', null);
106
        return $this;
107
    }
108
109
    /**
110
     * @inheritdoc
111
     */
112
    public function beforeSave($insert)
113
    {
114
        // Make sure score is calculated
115
        $this->getScore();
116
117
        return parent::beforeSave($insert);
118
    }
119
120
    /**
121
     * @inheritdoc
122
     */
123
    public static function instantiate($row)
124
    {
125
        $class = $row['class'] ?? static::class;
126
        return new $class;
127
    }
128
129
    /**
130
     * @inheritdoc
131
     */
132
    public function rules()
133
    {
134
        return array_merge(
135
            parent::rules(),
136
            $this->elementRules(),
137
            [
138
                [
139
                    [
140
                        'class'
141
                    ],
142
                    ElementMetricValidator::class
143
                ],
144
                [
145
                    [
146
                        'parentId',
147
                    ],
148
                    'number',
149
                    'integerOnly' => true
150
                ],
151
                [
152
                    [
153
                        'score',
154
                        'weight',
155
                    ],
156
                    'number'
157
                ],
158
                [
159
                    [
160
                        'elementId',
161
                        'class',
162
                        'weight',
163
                        'version',
164
                    ],
165
                    'required'
166
                ],
167
                [
168
                    [
169
                        'class',
170
                        'settings',
171
                        'score',
172
                        'weight',
173
                        'version',
174
                        'dateCalculated'
175
                    ],
176
                    'safe',
177
                    'on' => [
178
                        ModelHelper::SCENARIO_DEFAULT
179
                    ]
180
                ]
181
            ]
182
        );
183
    }
184
185
186
    /*******************************************
187
     * METRIC INTERFACE
188
     *******************************************/
189
190
    /**
191
     * @inheritdoc
192
     * @throws \ReflectionException
193
     */
194
    public static function displayName(): string
195
    {
196
        return preg_replace(
197
            '/(?<!^)([A-Z])/',
198
            ' $0',
199
            (new \ReflectionClass(static::class))
200
                ->getShortName()
201
        );
202
    }
203
204
    /**
205
     * @inheritdoc
206
     */
207
    public function getWeight(): float
208
    {
209
        return (float)$this->getAttribute('weight');
210
    }
211
212
    /**
213
     * @inheritdoc
214
     */
215
    public function getVersion(): string
216
    {
217
        return (string)$this->getAttribute('version');
218
    }
219
220
    /**
221
     * @inheritdoc
222
     */
223
    public function getScore(): float
224
    {
225
        if ($this->getAttribute('score') === null) {
226
            $this->setAttribute('score', $this->calculateScore() * $this->getWeight());
227
        }
228
229
        return (float)$this->getAttribute('score');
230
    }
231
232
    /**
233
     * @return DateTime
234
     */
235
    public function getDateCalculated(): DateTime
236
    {
237
        if (null === ($dateCalculated = $this->getAttribute('dateCalculated'))) {
238
            $dateCalculated = $this->defaultDateCalculated();
239
            $this->setAttribute('dateCalculated', $dateCalculated);
240
        }
241
242
        if (!$dateCalculated instanceof DateTime) {
243
            if (is_array($dateCalculated)) {
244
                $dateCalculated = $dateCalculated['date'] ?? $dateCalculated;
245
            }
246
247
            $dateCalculated = DateTimeHelper::toDateTime($dateCalculated);
248
            $this->setAttribute('dateCalculated', $dateCalculated);
249
        }
250
251
        return $dateCalculated;
252
    }
253
254
    /**
255
     * @return DateTime
256
     */
257
    protected function defaultDateCalculated(): DateTime
258
    {
259
        return DateTimeHelper::toDateTime(
260
            DateTimeHelper::currentUTCDateTime()->format('Y-m-d')
261
        );
262
    }
263
264
265
    /*******************************************
266
     * SETTINGS
267
     *******************************************/
268
269
    /**
270
     * @param string $attribute
271
     * @return mixed
272
     */
273
    public function getSettingsValue(string $attribute)
274
    {
275
        $settings = MetricHelper::resolveSettings(
276
            $this->getAttribute('settings')
277
        );
278
279
        return $settings[$attribute] ?? null;
280
    }
281
282
    /**
283
     * @param string $attribute
284
     * @param $value
285
     * @return $this
286
     */
287
    public function setSettingsValue(string $attribute, $value)
288
    {
289
        $settings = MetricHelper::resolveSettings(
290
            $this->getAttribute('settings')
291
        );
292
        $settings[$attribute] = $value;
293
        $this->setAttribute('settings', $settings);
294
295
        return $this;
296
    }
297
298
299
    /*******************************************
300
     * CONFIGURATION
301
     *******************************************/
302
303
    /**
304
     * @return array
305
     */
306
    public function toConfig(): array
307
    {
308
        return $this->toArray();
309
    }
310
}
311