Passed
Pull Request — master (#57)
by Stephen
03:23
created

Model   A

Complexity

Total Complexity 40

Size/Duplication

Total Lines 365
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 52
c 5
b 0
f 0
dl 0
loc 365
rs 9.2
wmc 40

30 Methods

Rating   Name   Duplication   Size   Complexity  
A howNew() 0 3 1
A newEloquentBuilder() 0 3 1
A query() 0 3 1
A getIsNewColumn() 0 3 1
A serializeDate() 0 3 1
A isNew() 0 7 2
A wasUpdated() 0 3 1
A wasCreated() 0 3 1
A getUpdatedDateAttribute() 0 3 1
A getUpdatedTimeAttribute() 0 3 1
A hasAttribute() 0 4 2
A getLabel() 0 3 1
A getIdHashAttribute() 0 3 1
A hasNullAttribute() 0 3 2
A getCreatedTimeAttribute() 0 3 1
A getUpdatedForHumansAttribute() 0 3 1
A getCreatedTimestampAttribute() 0 3 1
A getTimestampFormat() 0 3 1
A getDatetimeForHumans() 0 3 1
A getDatetimeAttribute() 0 3 1
A wasDeleted() 0 11 3
A getCreatedForHumansAttribute() 0 3 1
A mostRecentChange() 0 10 4
A getPrimaryKeyName() 0 4 1
A getUpdatedDiffForHumansAttribute() 0 3 1
A getCreatedDateAttribute() 0 3 1
A getCreatedDiffForHumansAttribute() 0 3 1
A hasAttributeFillable() 0 7 3
A getUpdatedTimestampAttribute() 0 3 1
A getTableName() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Model 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.

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 Model, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Sfneal\Models;
4
5
use Carbon\Carbon;
6
use DateTimeInterface;
7
use Illuminate\Database\Eloquent\Builder;
8
use Illuminate\Database\Eloquent\Model as EloquentModel;
9
use Illuminate\Database\Eloquent\SoftDeletes;
10
use Sfneal\Builders\QueryBuilder;
11
use Sfneal\Models\Traits\UploadDirectory;
12
13
#[\AllowDynamicProperties]
14
abstract class Model extends EloquentModel
15
{
16
    use SoftDeletes;
17
    use UploadDirectory;
18
19
    /**
20
     * Retrieve the datetime format used in the timestamp attribute accessors.
21
     *
22
     * @return string
23
     */
24
    protected $timestampFormat = 'Y-m-d h:i a';
25
26
    /**
27
     * Query Builder.
28
     *
29
     * @param  $query
30
     * @return QueryBuilder
31
     */
32
    public function newEloquentBuilder($query)
33
    {
34
        return new QueryBuilder($query);
35
    }
36
37
    /**
38
     * @return QueryBuilder|Builder
39
     */
40
    public static function query()
41
    {
42
        return parent::query();
43
    }
44
45
    /**
46
     * Prepare a date for array / JSON serialization.
47
     *
48
     * @param  DateTimeInterface  $date
49
     * @return string
50
     */
51
    protected function serializeDate(DateTimeInterface $date)
52
    {
53
        return $date->format('Y-m-d H:i:s');
54
    }
55
56
    /**
57
     * Max number of hours ago a model instance could have been created ago and considered 'new'.
58
     */
59
    private const IS_NEW_MAX_HOURS = 168;
60
61
    /**
62
     * Determine if a model instance 'is new' if it was created within the time frame.
63
     *
64
     * @return bool
65
     */
66
    public function isNew(): bool
67
    {
68
        if (empty($this->attributes['created_at'])) {
69
            return false;
70
        }
71
72
        return strtotime($this->attributes['created_at']) >= strtotime('-'.self::IS_NEW_MAX_HOURS.' hours');
73
    }
74
75
    /**
76
     * Determine how new a model instance is by subtracting the current time with the created_at time.
77
     *
78
     * @return float
79
     */
80
    public function howNew(): float
81
    {
82
        return round((time() - strtotime($this->attributes['created_at'])) / (60 * 60 * 24));
83
    }
84
85
    /**
86
     * Return the value of the 'is new' column (default is 'created_at').
87
     *
88
     * @return string
89
     */
90
    public function getIsNewColumn()
91
    {
92
        return $this->getCreatedAtColumn();
93
    }
94
95
    /**
96
     * Determine if a model has an attribute.
97
     *
98
     *  - Optionally determine if the attribute is fillable.
99
     *  - Allows $attr to be null for conditionals where a column may not exist
100
     *
101
     * @param  string  $key
102
     * @return bool
103
     */
104
    public function hasAttribute($key): bool
105
    {
106
        // Determine that the attribute exists
107
        return isset($key) && array_key_exists($key, $this->attributesToArray());
108
    }
109
110
    /**
111
     * Determine if a model has an attribute.
112
     *
113
     *  - Optionally determine if the attribute is fillable.
114
     *  - Allows $attr to be null for conditionals where a column may not exist
115
     *
116
     * @param  string  $key
117
     * @return bool
118
     */
119
    public function hasAttributeFillable($key): bool
120
    {
121
        // Determine that the attribute exists and weather it is fillable
122
        return
123
            isset($key) &&
124
            array_key_exists($key, $this->attributesToArray()) &&
125
            in_array($key, $this->getFillable());
126
    }
127
128
    /**
129
     * Determine if a model has attribute that is also null.
130
     *
131
     * @param  string  $attr
132
     * @return bool
133
     */
134
    public function hasNullAttribute(string $attr): bool
135
    {
136
        return $this->hasAttribute($attr) && is_null($this->getAttribute($attr));
137
    }
138
139
    /**
140
     * Retrieve an integer has of the model instance's ID.
141
     *
142
     * @return int
143
     */
144
    public function getIdHashAttribute(): int
145
    {
146
        return crc32($this->getKey());
147
    }
148
149
    /**
150
     * Returns the default 'label' for a model instance.
151
     *
152
     * @return mixed
153
     */
154
    public function getLabel()
155
    {
156
        return $this->getKey();
157
    }
158
159
    /**
160
     * Retrieve a Model's table name statically.
161
     *
162
     * @return mixed
163
     */
164
    public static function getTableName()
165
    {
166
        /** @phpstan-ignore-next-line */
167
        return (new static)->getTable();
168
    }
169
170
    /**
171
     * Retrieve a Model's primary key statically.
172
     *
173
     * @return mixed
174
     */
175
    public static function getPrimaryKeyName()
176
    {
177
        /** @phpstan-ignore-next-line */
178
        return (new static)->getKeyName();
179
    }
180
181
    /**
182
     * Determine if a Model was recently 'created'.
183
     *
184
     * @return bool
185
     */
186
    public function wasCreated(): bool
187
    {
188
        return $this->wasRecentlyCreated;
189
    }
190
191
    /**
192
     * Determine if a Model was recently 'updated'.
193
     *
194
     * @return bool
195
     */
196
    public function wasUpdated(): bool
197
    {
198
        return $this->wasChanged();
199
    }
200
201
    /**
202
     * Determine if a Model was recently 'deleted'.
203
     *
204
     * @return bool
205
     */
206
    public function wasDeleted(): bool
207
    {
208
        if (! $this->exists) {
209
            return true;
210
        }
211
212
        if (array_key_exists('deleted_at', $this->attributesToArray())) {
213
            return ! is_null($this->attributes['deleted_at']);
214
        }
215
216
        return false;
217
    }
218
219
    /**
220
     * Retrieve the most recent Model change.
221
     *
222
     * @return string
223
     */
224
    public function mostRecentChange(): string
225
    {
226
        if ($this->wasCreated()) {
227
            return 'created';
228
        } elseif ($this->wasUpdated()) {
229
            return 'updated';
230
        } elseif ($this->wasDeleted()) {
231
            return 'deleted';
232
        } else {
233
            return 'unchanged';
234
        }
235
    }
236
237
    /**
238
     * Retrieve the 'timestampFormat' property.
239
     *
240
     * @return string
241
     */
242
    public function getTimestampFormat(): string
243
    {
244
        return $this->timestampFormat;
245
    }
246
247
    /**
248
     * Retrieve the 'timestampFormatForHumans' property.
249
     *
250
     * @param  int  $stringToTime
251
     * @return string
252
     */
253
    protected function getDatetimeForHumans(int $stringToTime): string
254
    {
255
        return date('F j, Y', $stringToTime).' at '.date('g:i a', $stringToTime);
256
    }
257
258
    /**
259
     * Retrieve the 'created_at' attribute mutated to human readable datetime.
260
     *
261
     * @return string
262
     */
263
    public function getDatetimeAttribute(): string
264
    {
265
        return date('Y-m-d h:i a', strtotime($this->attributes['created_at']));
266
    }
267
268
    /**
269
     * Retrieve the 'created_at' attribute mutated to timestamp string.
270
     *
271
     *  - 'created_timestamp' attribute accessor
272
     *
273
     * @return string
274
     */
275
    public function getCreatedTimestampAttribute(): string
276
    {
277
        return date($this->getTimestampFormat(), strtotime($this->attributes['created_at']));
278
    }
279
280
    /**
281
     * Retrieve the 'created_for_humans' attribute mutated to a timestamp for humans string.
282
     *
283
     *  - 'created_for_humans' attribute accessor
284
     *
285
     * @return string
286
     */
287
    public function getCreatedForHumansAttribute(): string
288
    {
289
        return $this->getDatetimeForHumans(strtotime($this->attributes['created_at']));
290
    }
291
292
    /**
293
     * Retrieve the 'created_at' attribute mutated to difference for humans string.
294
     *
295
     *  - 'created_for_humans' attribute accessor
296
     *
297
     * @return string
298
     */
299
    public function getCreatedDiffForHumansAttribute(): string
300
    {
301
        return (new Carbon($this->attributes['created_at']))->diffForHumans();
302
    }
303
304
    /**
305
     * Access the 'creation_date' attribute that returns the attribute in 'Y-m-d' format.
306
     *
307
     * @return string
308
     */
309
    public function getCreatedDateAttribute(): string
310
    {
311
        return date('Y-m-d', strtotime($this->attributes['created_at']));
312
    }
313
314
    /**
315
     * Access the 'creation_time' attribute that returns the attribute in 'h:i A' format.
316
     *
317
     * @return string
318
     */
319
    public function getCreatedTimeAttribute(): string
320
    {
321
        return date('h:i A', strtotime($this->attributes['created_at']));
322
    }
323
324
    /**
325
     * Retrieve the 'updated_at' attribute mutated to timestamp string.
326
     *
327
     *  - 'updated_timestamp' attribute accessor
328
     *
329
     * @return string
330
     */
331
    public function getUpdatedTimestampAttribute(): string
332
    {
333
        return date($this->getTimestampFormat(), strtotime($this->attributes['updated_at']));
334
    }
335
336
    /**
337
     * Retrieve the 'updated_for_humans' attribute mutated to a timestamp for humans string.
338
     *
339
     *  - 'updated_for_humans' attribute accessor
340
     *
341
     * @return string
342
     */
343
    public function getUpdatedForHumansAttribute(): string
344
    {
345
        return $this->getDatetimeForHumans(strtotime($this->attributes['updated_at']));
346
    }
347
348
    /**
349
     * Retrieve the 'updated_at' attribute mutated to difference for humans string.
350
     *
351
     *  - 'updated_for_humans' attribute accessor
352
     *
353
     * @return string
354
     */
355
    public function getUpdatedDiffForHumansAttribute(): string
356
    {
357
        return (new Carbon($this->attributes['updated_at']))->diffForHumans();
358
    }
359
360
    /**
361
     * Access the 'updated_date' attribute that returns the attribute in 'Y-m-d' format.
362
     *
363
     * @return string
364
     */
365
    public function getUpdatedDateAttribute(): string
366
    {
367
        return date('Y-m-d', strtotime($this->attributes['updated_at']));
368
    }
369
370
    /**
371
     * Access the 'updated_time' attribute that returns the attribute in 'h:i A' format.
372
     *
373
     * @return string
374
     */
375
    public function getUpdatedTimeAttribute(): string
376
    {
377
        return date('h:i A', strtotime($this->attributes['updated_at']));
378
    }
379
}
380