Completed
Pull Request — master (#1)
by Oliver
14:08
created

Carbonated::carbonatedAccessor()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 23
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 8.5906
c 0
b 0
f 0
cc 5
eloc 10
nc 8
nop 2
1
<?php
2
3
namespace ThisVessel;
4
5
use Carbon\Carbon;
6
use Request;
7
8
trait Carbonated
9
{
10
    /**
11
     * Store carbon instances for reuse.
12
     *
13
     * @var object
14
     */
15
    protected $carbonInstances;
16
17
    /**
18
     * Indicate whether accessors should be overridden to return carbon instances.
19
     *
20
     * @var bool
21
     */
22
    protected $returnCarbon = false;
23
24
    /**
25
     * Get the attributes that should be handled as carbonated timestamps.
26
     *
27
     * @return array
28
     */
29
    public function carbonatedTimestamps()
30
    {
31
        // Add default fields for schema builder's timestamps() and softDeletes().
32
        $defaults = [static::CREATED_AT, static::UPDATED_AT, 'deleted_at'];
33
34
        return $this->ensureProperty($this, 'carbonatedTimestamps') ? array_unique(array_merge($this->carbonatedTimestamps, $defaults)) : $defaults;
1 ignored issue
show
Bug introduced by
The property carbonatedTimestamps does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
35
    }
36
37
    /**
38
     * Get the attributes that should be handled as carbonated dates.
39
     *
40
     * @return array
41
     */
42
    public function carbonatedDates()
43
    {
44
        return $this->ensureProperty($this, 'carbonatedDates') ? (array) $this->carbonatedDates : [];
45
    }
46
47
    /**
48
     * Get the attributes that should be handled as carbonated times.
49
     *
50
     * @return array
51
     */
52
    public function carbonatedTimes()
53
    {
54
        return $this->ensureProperty($this, 'carbonatedTimes') ? (array) $this->carbonatedTimes : [];
55
    }
56
57
    /**
58
     * Get all attributes that should be handled by carbonated.
59
     *
60
     * @return array
61
     */
62
    public function carbonatedAttributes()
63
    {
64
        return array_merge($this->carbonatedTimestamps(), $this->carbonatedDates(), $this->carbonatedTimes());
65
    }
66
67
    /**
68
     * Get carbonated attribute type.
69
     *
70
     * @param string $key
71
     *
72
     * @return string
73
     */
74
    public function carbonatedAttributeType($key)
75
    {
76
        if (in_array($key, $this->carbonatedTimestamps())) {
77
            return 'timestamp';
78
        } elseif (in_array($key, $this->carbonatedDates())) {
79
            return 'date';
80
        } elseif (in_array($key, $this->carbonatedTimes())) {
81
            return 'time';
82
        }
83
84
        return false;
85
    }
86
87
    /**
88
     * Get the intended timestamp format for view output.
89
     *
90
     * @return string
91
     */
92
    public function carbonatedTimestampFormat()
93
    {
94
        return $this->ensureProperty($this, 'carbonatedTimestampFormat') ? (string) $this->carbonatedTimestampFormat : 'M d, Y g:ia';
1 ignored issue
show
Bug introduced by
The property carbonatedTimestampFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
95
    }
96
97
    /**
98
     * Get the intended date format for view output.
99
     *
100
     * @return string
101
     */
102
    public function carbonatedDateFormat()
103
    {
104
        return $this->ensureProperty($this, 'carbonatedDateFormat') ? (string) $this->carbonatedDateFormat : 'M d, Y';
1 ignored issue
show
Bug introduced by
The property carbonatedDateFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
105
    }
106
107
    /**
108
     * Get the intended date format for view output.
109
     *
110
     * @return string
111
     */
112
    public function carbonatedTimeFormat()
113
    {
114
        return $this->ensureProperty($this, 'carbonatedTimeFormat') ? (string) $this->carbonatedTimeFormat : 'g:ia';
1 ignored issue
show
Bug introduced by
The property carbonatedTimeFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
115
    }
116
117
    /**
118
     * Get the intended timezone for view output.
119
     *
120
     * @return string
121
     */
122
    public function carbonatedTimezone()
123
    {
124
        // Check for $carbonatedTimezone property in model.
125
        if ($this->ensureProperty($this, 'carbonatedTimezone')) {
126
            return (string) $this->carbonatedTimezone;
1 ignored issue
show
Bug introduced by
The property carbonatedTimezone does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
127
        } // If not, check for an authenticated user with a $timezone property.
128
        elseif (class_exists(\Auth::class) && \Auth::check() && \Auth::user()->timezone) {
129
            return (string) \Auth::user()->timezone;
130
        }
131
132
        // Otherwise use same timezone as database.
133
        return $this->databaseTimezone();
134
    }
135
136
    /**
137
     * Get the intended timestamp for json output.
138
     *
139
     * @return string
140
     */
141
    public function jsonTimestampFormat()
142
    {
143
        return $this->ensureProperty($this, 'jsonTimestampFormat') ? (string) $this->jsonTimestampFormat : $this->databaseTimestampFormat();
1 ignored issue
show
Bug introduced by
The property jsonTimestampFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
144
    }
145
146
    /**
147
     * Get the intended date for json output.
148
     *
149
     * @return string
150
     */
151
    public function jsonDateFormat()
152
    {
153
        return $this->ensureProperty($this, 'jsonDateFormat') ? (string) $this->jsonDateFormat : $this->databaseDateFormat();
1 ignored issue
show
Bug introduced by
The property jsonDateFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
154
    }
155
156
    /**
157
     * Get the intended time for json output.
158
     *
159
     * @return string
160
     */
161
    public function jsonTimeFormat()
162
    {
163
        return $this->ensureProperty($this, 'jsonTimeFormat') ? (string) $this->jsonTimeFormat : $this->databaseTimeFormat();
1 ignored issue
show
Bug introduced by
The property jsonTimeFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
164
    }
165
166
    /**
167
     * Get the intended timezone for json output.
168
     *
169
     * @return string
170
     */
171
    public function jsonTimezone()
172
    {
173
        // Check for $jsonTimezone property in model.
174
        if ($this->ensureProperty($this, 'jsonTimezone')) {
175
            return (string) $this->jsonTimezone;
1 ignored issue
show
Bug introduced by
The property jsonTimezone does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
176
        }
177
178
        // Otherwise use same timezone as database.
179
        return $this->databaseTimezone();
180
    }
181
182
    /**
183
     * Get the intended database format for timestamp storage.
184
     *
185
     * @return string
186
     */
187
    public function databaseTimestampFormat()
188
    {
189
        return $this->ensureProperty($this, 'databaseTimestampFormat') ? (string) $this->databaseTimestampFormat : 'Y-m-d H:i:s';
1 ignored issue
show
Bug introduced by
The property databaseTimestampFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
190
    }
191
192
    /**
193
     * Get the intended database format for date storage.
194
     *
195
     * @return string
196
     */
197
    public function databaseDateFormat()
198
    {
199
        return $this->ensureProperty($this, 'databaseDateFormat') ? (string) $this->databaseDateFormat : 'Y-m-d';
1 ignored issue
show
Bug introduced by
The property databaseDateFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
200
    }
201
202
    /**
203
     * Get the intended database format for time storage.
204
     *
205
     * @return string
206
     */
207
    public function databaseTimeFormat()
208
    {
209
        return $this->ensureProperty($this, 'databaseTimeFormat') ? (string) $this->databaseTimeFormat : 'H:i:s';
1 ignored issue
show
Bug introduced by
The property databaseTimeFormat does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
210
    }
211
212
    /**
213
     * Get the intended timezone for database storage.
214
     *
215
     * @return string
216
     */
217
    public function databaseTimezone()
218
    {
219
        // Check for $databaseTimezone property in model.
220
        if ($this->ensureProperty($this, 'databaseTimezone')) {
221
            return (string) $this->databaseTimezone;
1 ignored issue
show
Bug introduced by
The property databaseTimezone does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
222
        }
223
224
        // Otherwise use app's timezone configuration.
225
        return (string) function_exists('config') ? config('app.timezone') : 'UTC';
226
    }
227
228
    /**
229
     * Store and return carbon instances for reuse.
230
     *
231
     * @return object
232
     */
233
    protected function carbonInstances()
234
    {
235
        // Check if date/time fields have already been carbonated.
236
        if ($this->carbonInstances) {
237
            return $this->carbonInstances;
238
        }
239
240
        // If not, get timezones.
241
        $databaseTimezone = $this->databaseTimezone();
242
        $carbonatedTimezone = $this->carbonatedTimezone();
243
244
        // Get database field formats.
245
        foreach ($this->carbonatedTimestamps() as $field) {
246
            $fieldFormats[$field] = $this->databaseTimestampFormat();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$fieldFormats was never initialized. Although not strictly required by PHP, it is generally a good practice to add $fieldFormats = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
247
        }
248
        foreach ($this->carbonatedDates() as $field) {
249
            $fieldFormats[$field] = $this->databaseDateFormat();
0 ignored issues
show
Bug introduced by
The variable $fieldFormats does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
250
        }
251
        foreach ($this->carbonatedTimes() as $field) {
252
            $fieldFormats[$field] = $this->databaseTimeFormat();
253
        }
254
255
        // Create Carbon instances.
256
        foreach ($fieldFormats as $field => $format) {
257
            $value = isset($this->attributes[$field]) ? $this->attributes[$field] : null;
1 ignored issue
show
Bug introduced by
The property attributes does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
258
            $carbonInstance = $value ? Carbon::createFromFormat($format, $value, $databaseTimezone) : null;
259
            $carbonInstances[$field] = $carbonInstance ? $carbonInstance->timezone($carbonatedTimezone) : null;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$carbonInstances was never initialized. Although not strictly required by PHP, it is generally a good practice to add $carbonInstances = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
260
        }
261
262
        // Store Carbon instances for future use.
263
        $this->carbonInstances = isset($carbonInstances) ? (object) $carbonInstances : null;
264
265
        // Return Carbon instances.
266
        return $this->carbonInstances;
267
    }
268
269
    /**
270
     * Return a clone of $this object and modify it's accessors.
271
     *
272
     * @return $this
273
     */
274
    public function getWithCarbonAttribute()
275
    {
276
        // Clone $this to preserve it's state.
277
        $clone = clone $this;
278
279
        // Modify clone's accessors.
280
        $clone->returnCarbon = true;
281
282
        // Return clone.
283
        return $clone;
284
    }
285
286
    /**
287
     * Access and format for front end.
288
     *
289
     * @param string $key
290
     * @param bool   $json
291
     *
292
     * @return string
293
     */
294
    public function carbonatedAccessor($key, $json = false)
295
    {
296
        // Initial accesor setup.
297
        $accessorType = $json ? 'json' : 'carbonated';
298
        $fieldType = $this->carbonatedAttributeType($key);
299
300
        // Get output format and timezone for conversion.
301
        $outputFormat = $this->{$accessorType.ucfirst($fieldType).'Format'}();
302
        $outputTimezone = $this->{$accessorType.'Timezone'}();
303
304
        // Get Carbon instance.
305
        /** @var Carbon $carbonInstance */
306
        $carbonInstance = $this->carbonInstances()->$key;
307
308
        // Return formatted value.
309
        $timezonedInstance = $carbonInstance->timezone($outputTimezone);
310
311
        if ($this->useLocalizedFormats()) {
312
            return $carbonInstance ? $timezonedInstance->formatLocalized($outputFormat) : null;
313
        }
314
315
        return $carbonInstance ? $timezonedInstance->format($outputFormat) : null;
316
    }
317
318
    /**
319
     * Mutate to a storable value for database.
320
     *
321
     * @param string $key
322
     * @param mixed  $value
323
     *
324
     * @return string
325
     */
326
    public function carbonatedMutator($key, $value)
327
    {
328
        // Get type.
329
        $fieldType = $this->carbonatedAttributeType($key);
330
331
        // Get database format and timezone.
332
        $databaseFormat = $this->{'database'.ucfirst($fieldType).'Format'}();
333
        $databaseTimezone = $this->databaseTimezone();
334
335
        // If value is DateTime instance, convert to Carbon instance.
336
        if ($value instanceof \DateTime) {
337
            $value = Carbon::instance($value);
338
        }
339
340
        // It value is Carbon intance, return storable value.
341
        if ($value instanceof Carbon) {
342
            return $value->timezone($databaseTimezone)->format($databaseFormat);
343
        }
344
345
        // Otherwise, get input format and timezone for conversion.
346
        if (static::requestIsJson()) {
347
            $inputFormat = $this->{'json'.ucfirst($fieldType).'Format'}();
348
            $inputTimezone = $this->jsonTimezone();
349
        } else {
350
            $inputFormat = $this->{'carbonated'.ucfirst($fieldType).'Format'}();
351
            $inputTimezone = $this->carbonatedTimezone();
352
        }
353
354
        // Convert to Carbon instance.
355
        $carbonInstance = $value ? Carbon::createFromFormat($inputFormat, $value, $inputTimezone) : null;
356
357
        // Return storable value.
358
        return $carbonInstance ? $carbonInstance->timezone($databaseTimezone)->format($databaseFormat) : null;
359
    }
360
361
    /**
362
     * Check if request is some type of JSON (purposefully more lenient than current Request::isJson() helper).
363
     *
364
     * @return bool
365
     */
366
    public static function requestIsJson()
367
    {
368
        return str_contains(Request::header('CONTENT_TYPE'), 'json');
0 ignored issues
show
Bug introduced by
It seems like \Request::header('CONTENT_TYPE') targeting Illuminate\Http\Concerns...actsWithInput::header() can also be of type array; however, str_contains() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
369
    }
370
371
    /**
372
     * Override default getDates() to allow created_at and updated_at handling by carbonated.
373
     *
374
     * @return array
375
     */
376
    public function getDates()
377
    {
378
        return (array) $this->dates;
379
    }
380
381
    /**
382
     * Override default freshTimestamp() to be more explicit in setting timezone for storage.
383
     *
384
     * @return \Carbon\Carbon
385
     */
386
    public function freshTimestamp()
387
    {
388
        $databaseTimezone = $this->databaseTimezone();
389
390
        return Carbon::now($databaseTimezone);
391
    }
392
393
    /**
394
     * Override default toArray() to include our own accessors.
395
     *
396
     * @param bool $useJsonAccessors
397
     *
398
     * @return array
399
     */
400
    public function toArray($useJsonAccessors = false)
401
    {
402
        $attributes = $this->attributesToArray();
1 ignored issue
show
Bug introduced by
The method attributesToArray() does not exist on ThisVessel\Carbonated. Did you maybe mean toArray()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
403
404
        // If returning JSON output, reference our own accessors for relevant date/time fields.
405
        if ($useJsonAccessors) {
406
            foreach ($attributes as $key => $value) {
407
                if (!$this->hasGetMutator($key) && in_array($key, $this->carbonatedAttributes())) {
1 ignored issue
show
Bug introduced by
It seems like hasGetMutator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
408
                    $attributes[$key] = $this->carbonatedAccessor($key, true);
409
                }
410
            }
411
        }
412
413
        return array_merge($attributes, $this->relationsToArray());
1 ignored issue
show
Bug introduced by
The method relationsToArray() does not exist on ThisVessel\Carbonated. Did you maybe mean toArray()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
414
    }
415
416
    /**
417
     * Override default jsonSerialize() to set $useJsonAccessors parameter.
418
     *
419
     * @return array
420
     */
421
    public function jsonSerialize()
422
    {
423
        return $this->toArray(true);
424
    }
425
426
    /**
427
     * Override default getAttributeValue() to include our own accessors.
428
     *
429
     * @param string $key
430
     *
431
     * @return mixed
432
     */
433
    public function getAttributeValue($key)
434
    {
435
        $value = $this->getAttributeFromArray($key);
1 ignored issue
show
Bug introduced by
It seems like getAttributeFromArray() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
436
437
        // Check for the presence of an accessor in our model.
438
        if ($this->hasGetMutator($key)) {
1 ignored issue
show
Bug introduced by
It seems like hasGetMutator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
439
            return $this->mutateAttribute($key, $value);
1 ignored issue
show
Bug introduced by
It seems like mutateAttribute() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
440
        }
441
442
        // If no accessor found, reference our own accessors for relevant date/time fields.
443
        if (in_array($key, $this->carbonatedAttributes())) {
444
            $value = $this->returnCarbon ? $this->carbonInstances()->$key : $this->carbonatedAccessor($key);
445
        }
446
447
        // Otherwise, revert to default Eloquent behavour.
448
        if ($this->hasCast($key)) {
1 ignored issue
show
Bug introduced by
It seems like hasCast() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
449
            $value = $this->castAttribute($key, $value);
1 ignored issue
show
Bug introduced by
It seems like castAttribute() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
450
        } elseif (in_array($key, $this->getDates())) {
451
            if (!is_null($value)) {
452
                return $this->asDateTime($value);
1 ignored issue
show
Bug introduced by
It seems like asDateTime() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
453
            }
454
        }
455
456
        return $value;
457
    }
458
459
    /**
460
     * Override default setAttribute() to include our own mutators.
461
     *
462
     * @param string $key
463
     * @param mixed  $value
464
     *
465
     * @return void
466
     */
467
    public function setAttribute($key, $value)
468
    {
469
        // Check for the presence of a mutator in our model.
470
        if ($this->hasSetMutator($key)) {
1 ignored issue
show
Bug introduced by
It seems like hasSetMutator() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
471
            $method = 'set'.studly_case($key).'Attribute';
472
473
            return $this->{$method}($value);
474
        } // If no mutator found, reference our own mutators for relevant date/time fields.
475
        elseif (in_array($key, $this->carbonatedAttributes())) {
476
            $value = $this->carbonatedMutator($key, $value);
477
        } // Otherwise, revert to default Eloquent behavour.
478
        elseif (in_array($key, $this->getDates()) && $value) {
479
            $value = $this->fromDateTime($value);
1 ignored issue
show
Bug introduced by
It seems like fromDateTime() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
480
        }
481
482
        if ($this->isJsonCastable($key)) {
1 ignored issue
show
Bug introduced by
It seems like isJsonCastable() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
483
            $value = json_encode($value);
484
        }
485
486
        $this->attributes[$key] = $value;
487
    }
488
489
    /**
490
     * @param object $carbonInstances
491
     */
492
    public function setCarbonInstances($carbonInstances)
493
    {
494
        if (!is_object($carbonInstances)) {
495
            throw new \InvalidArgumentException('carbonInstances must be an object.');
496
        }
497
        $this->carbonInstances = $carbonInstances;
498
    }
499
500
    private function ensureProperty($instance, $propertyName)
501
    {
502
        if (!property_exists($instance, $propertyName)) {
503
            return false;
504
        }
505
506
        // Check property value for null and false values
507
        if (empty($instance->{$propertyName})) {
508
            return false;
509
        }
510
511
        return true;
512
    }
513
514
    private function useLocalizedFormats()
515
    {
516
        $localize = config('carbonated.localization', false);
517
518
        return $localize;
519
    }
520
}
521