Completed
Pull Request — master (#23)
by Lucas
07:42
created

GeneratesUuid::bootGeneratesUuid()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 8
cts 8
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 1
nop 0
crap 4
1
<?php
2
3
namespace Dyrynda\Database\Support;
4
5
/**
6
 * UUID generation trait.
7
 *
8
 * Include this trait in any Eloquent model where you wish to automatically set
9
 * a UUID field. When saving, if the UUID field has not been set, generate a
10
 * new UUID value, which will be set on the model and saved by Eloquent.
11
 *
12
 * @copyright 2017 Michael Dyrynda
13
 * @author    Michael Dyrynda <[email protected]>
14
 * @license   MIT
15
 */
16
trait GeneratesUuid
17
{
18
    /**
19
     * The UUID versions.
20
     *
21
     * @var array
22
     */
23
    protected $uuidVersions = [
24
        'uuid1',
25
        'uuid3',
26
        'uuid4',
27
        'uuid5',
28
    ];
29
30
    /**
31
     * Determine whether an attribute should be cast to a native type.
32
     *
33
     * @param  string  $key
34
     * @param  array|string|null  $types
35
     * @return bool
36
     */
37
    abstract public function hasCast($key, $types = null);
38
39
    /**
40
     * Boot the trait, adding a creating observer.
41
     *
42
     * When persisting a new model instance, we resolve the UUID field, then set
43
     * a fresh UUID, taking into account if we need to cast to binary or not.
44
     *
45
     * @return void
46
     */
47
    public static function bootGeneratesUuid()
48
    {
49 6
        static::creating(function ($model) {
50 6
            $uuid = $model->resolveUuid();
51
52 6
            if (isset($model->attributes['uuid']) && ! is_null($model->attributes['uuid'])) {
53 4
                $uuid = $uuid->fromString(strtolower($model->attributes['uuid']));
54 4
            }
55
56 6
            $model->attributes['uuid'] = $model->hasCast('uuid') ? $uuid->getBytes() : $uuid->toString();
57 6
        });
58 2
    }
59
60
    /**
61
     * Resolve a UUID instance for the configured version.
62
     *
63
     * @return \Ramsey\Uuid\Uuid
64
     */
65 6
    public function resolveUuid()
66
    {
67 6
        return call_user_func("\Ramsey\Uuid\Uuid::{$this->resolveUuidVersion()}");
68
    }
69
70
    /**
71
     * Resolve the UUID version to use when setting the UUID value. Default to uuid4.
72
     *
73
     * @return string
74
     */
75 11
    public function resolveUuidVersion()
76
    {
77 11
        if (property_exists($this, 'uuidVersion') && in_array($this->uuidVersion, $this->uuidVersions)) {
78 4
            return $this->uuidVersion;
79
        }
80
81 7
        return 'uuid4';
82
    }
83
84
    /**
85
     * Scope queries to find by UUID.
86
     *
87
     * @param  \Illuminate\Database\Eloquent\Builder  $query
88
     * @param  string  $uuid
89
     *
90
     * @return \Illuminate\Database\Eloquent\Builder
91
     */
92 2
    public function scopeWhereUuid($query, $uuid)
93
    {
94 2
        if ($this->hasCast('uuid')) {
95 1
            $uuid = $this->resolveUuid()->fromString($uuid)->getBytes();
96 1
        }
97
98 2
        return $query->where('uuid', $uuid);
99
    }
100
101
    /**
102
     * Cast an attribute to a native PHP type.
103
     *
104
     * @param  string  $key
105
     * @param  mixed  $value
106
     * @return mixed
107
     */
108 2
    protected function castAttribute($key, $value)
109
    {
110 2
        if ($key === 'uuid' && ! is_null($value)) {
111 2
            return $this->resolveUuid()->fromBytes($value)->toString();
112
        }
113
114
        return parent::castAttribute($key, $value);
115
    }
116
}
117