Passed
Pull Request — master (#50)
by
unknown
02:10
created

GeneratesUuid::scopeWhereUuid()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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