Passed
Pull Request — master (#59)
by
unknown
01:46
created

GeneratesUuid::bootGeneratesUuid()   A

Complexity

Conditions 5
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 6
nc 1
nop 0
dl 0
loc 11
ccs 6
cts 6
cp 1
crap 5
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
namespace Dyrynda\Database\Support;
4
5
use Ramsey\Uuid\Uuid;
6
use Illuminate\Support\Str;
7
8
/**
9
 * UUID generation trait.
10
 *
11
 * Include this trait in any Eloquent model where you wish to automatically set
12
 * a UUID field. When saving, if the UUID field has not been set, generate a
13
 * new UUID value, which will be set on the model and saved by Eloquent.
14
 *
15
 * @copyright 2017 Michael Dyrynda
16
 * @author    Michael Dyrynda <[email protected]>
17
 * @license   MIT
18
 *
19
 * @property  string  $uuidVersion
20
 */
21
trait GeneratesUuid
22
{
23
    /**
24
     * The UUID versions.
25
     *
26
     * @var array
27
     */
28
    protected $uuidVersions = [
29
        'uuid1',
30
        'uuid3',
31
        'uuid4',
32
        'uuid5',
33
        'ordered',
34
    ];
35
36
    /**
37
     * Determine whether an attribute should be cast to a native type.
38
     *
39
     * @param  string  $key
40
     * @param  array|string|null  $types
41
     * @return bool
42
     */
43
     abstract public function hasCast($key, $types = null);
44
45
    /**
46
     * Boot the trait, adding a creating observer.
47
     *
48
     * When persisting a new model instance, we resolve the UUID field, then set
49
     * a fresh UUID, taking into account if we need to cast to binary or not.
50
     *
51
     * @return void
52
     */
53 10
    public static function bootGeneratesUuid()
54
    {
55
        static::creating(function ($model) {
56
            /* @var \Illuminate\Database\Eloquent\Model|static $model */
57 10
            $uuid = $model->resolveUuid();
58 10
            foreach($model->uuidColumns() as $item) {
59 10
                if (isset($model->attributes[$item]) && ! is_null($model->attributes[$item])) {
60
                    /* @var \Ramsey\Uuid\Uuid $uuid */
61 5
                    $uuid = $uuid->fromString(strtolower($model->attributes[$item]));
62
                }
63 10
                $model->attributes[$item] = $model->hasCast($item, 'uuid') ? $uuid->getBytes() : $uuid->toString();
0 ignored issues
show
Bug Best Practice introduced by
The property attributes does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
64
            }
65
66 10
        });
67 6
    }
68
69
    /**
70
     * The name of the column that should be used for the UUID.
71
     *
72
     * @return string
73
     */
74 7
    public function uuidColumn()
75
    {
76 7
        return 'uuid';
77
    }
78
79
80
    /**
81
     * The names of the columns that should be used for the UUID.
82
     *
83
     * @return array
84
     */
85 9
    public function uuidColumns()
86
    {
87 9
        return [$this->uuidColumn()];
88
    }
89
90
91
92
    /**
93
     * Resolve a UUID instance for the configured version.
94
     *
95
     * @return \Ramsey\Uuid\Uuid
96
     */
97 10
    public function resolveUuid()
98
    {
99 10
        if (($version = $this->resolveUuidVersion()) == 'ordered') {
100 1
            return Str::orderedUuid();
101
        }
102
103 9
        return call_user_func([Uuid::class, $version]);
104
    }
105
106
    /**
107
     * Resolve the UUID version to use when setting the UUID value. Default to uuid4.
108
     *
109
     * @return string
110
     */
111 16
    public function resolveUuidVersion()
112
    {
113 16
        if (property_exists($this, 'uuidVersion') && in_array($this->uuidVersion, $this->uuidVersions)) {
114 6
            return $this->uuidVersion;
115
        }
116
117 10
        return 'uuid4';
118
    }
119
120
    /**
121
     * Scope queries to find by UUID.
122
     *
123
     * @param  \Illuminate\Database\Eloquent\Builder  $query
124
     * @param  string  $uuid
125
     * @param  string  $uuidColumn
126
     *
127
     * @return \Illuminate\Database\Eloquent\Builder
128
     */
129 3
    public function scopeWhereUuid($query, $uuid, $uuidColumn = null)
130
    {
131
132 3
        $uuidColumn = isset($uuidColumn) && in_array($uuidColumn, $this->uuidColumns()) ? $uuidColumn : $this->uuidColumns()[0];
133 3
        if ($this->hasCast($uuidColumn)) {
134 2
            $uuid = $this->resolveUuid()->fromString($uuid)->getBytes();
135
        }
136
137 3
        return $query->where($uuidColumn, $uuid);
138
    }
139
140
    /**
141
     * Cast an attribute to a native PHP type.
142
     *
143
     * @param  string  $key
144
     * @param  mixed  $value
145
     * @return mixed
146
     */
147 5
    protected function castAttribute($key, $value)
148
    {
149 5
        if (in_array($key, $this->uuidColumns()) && ! empty($value)) {
150 5
            return $this->resolveUuid()->fromBytes($value)->toString();
151
        }
152
153
        return parent::castAttribute($key, $value);
154
    }
155
}
156