1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace LeKoala\Uuid; |
4
|
|
|
|
5
|
|
|
use Ramsey\Uuid\Uuid; |
6
|
|
|
use SilverStripe\ORM\DB; |
7
|
|
|
use Tuupola\Base62Proxy; |
8
|
|
|
use SilverStripe\Core\Convert; |
9
|
|
|
use SilverStripe\ORM\DataObject; |
10
|
|
|
use SilverStripe\Forms\FormField; |
11
|
|
|
use SilverStripe\ORM\FieldType\DBField; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* A uuid field that stores Uuid in binary formats |
15
|
|
|
* |
16
|
|
|
* Some knowledge... |
17
|
|
|
* |
18
|
|
|
* @link https://paragonie.com/blog/2015/09/comprehensive-guide-url-parameter-encryption-in-php |
19
|
|
|
* @link https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ |
20
|
|
|
* @link https://mariadb.com/kb/en/library/guiduuid-performance/ |
21
|
|
|
* @link https://stackoverflow.com/questions/28251144/inserting-and-selecting-uuids-as-binary16 |
22
|
|
|
*/ |
23
|
|
|
class DBUuid extends DBField |
24
|
|
|
{ |
25
|
|
|
const BINARY_LENGTH = 16; |
26
|
|
|
const STRING_LENGTH = 36; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* An expression to use in your custom queries |
30
|
|
|
* |
31
|
|
|
* @link https://stackoverflow.com/questions/37168797/how-to-format-uuid-string-from-binary-column-in-mysql-mariadb |
32
|
|
|
* @return string |
33
|
|
|
*/ |
34
|
|
|
public static function sqlFormatExpr() |
35
|
|
|
{ |
36
|
|
|
$sql = <<<SQL |
37
|
|
|
LOWER(CONCAT( |
38
|
|
|
SUBSTR(HEX(Uuid), 1, 8), '-', |
39
|
|
|
SUBSTR(HEX(Uuid), 9, 4), '-', |
40
|
|
|
SUBSTR(HEX(Uuid), 13, 4), '-', |
41
|
|
|
SUBSTR(HEX(Uuid), 17, 4), '-', |
42
|
|
|
SUBSTR(HEX(Uuid), 21) |
43
|
|
|
)) AS UuidFormatted |
44
|
|
|
SQL; |
45
|
|
|
return $sql; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* This can be used with ->where clause |
50
|
|
|
* |
51
|
|
|
* @param string $type like, = |
52
|
|
|
* @param string $value |
53
|
|
|
* @return string |
54
|
|
|
*/ |
55
|
|
|
public function filterExpression($type, $value) |
56
|
|
|
{ |
57
|
|
|
if ($type == "like") { |
58
|
|
|
$value = "%$value%"; |
59
|
|
|
} |
60
|
|
|
$value = str_replace('-', '', $value); |
61
|
|
|
/** @var string $value */ |
62
|
|
|
$value = Convert::raw2sql($value, true); |
63
|
|
|
return "LOWER(HEX({$this->name})) $type $value"; |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @return void |
68
|
|
|
*/ |
69
|
|
|
public function requireField() |
70
|
|
|
{ |
71
|
|
|
// Use direct sql statement here |
72
|
|
|
$sql = "binary(16)"; |
73
|
|
|
// In postgres, it's bytea, there is also an uuid but we would need some postgres specific logic |
74
|
|
|
// @link https://stackoverflow.com/questions/26990559/convert-mysql-binary-to-postgresql-bytea |
75
|
|
|
$class = strtolower(get_class(DB::get_conn())); |
76
|
|
|
if (strpos($class, 'postgres') !== false) { |
77
|
|
|
$sql = 'bytea'; |
78
|
|
|
} |
79
|
|
|
DB::require_field($this->tableName, $this->name, $sql); |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @return string A uuid identifier like 0564a64ecdd4a2-7731-3233-3435-7cea2b |
84
|
|
|
*/ |
85
|
|
|
public function Nice() |
86
|
|
|
{ |
87
|
|
|
if (!$this->value) { |
88
|
|
|
return $this->nullValue(); |
|
|
|
|
89
|
|
|
} |
90
|
|
|
return Uuid::fromBytes($this->value)->toString(); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Return raw value since we store binary(16) representation |
95
|
|
|
* |
96
|
|
|
* @return string The binary representation like b"\x05d¦NÍÔ¢w12345|ê+ |
97
|
|
|
*/ |
98
|
|
|
public function Bytes() |
99
|
|
|
{ |
100
|
|
|
if (!$this->value) { |
101
|
|
|
return $this->nullValue(); |
|
|
|
|
102
|
|
|
} |
103
|
|
|
return $this->value; |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Perfect for urls or html usage |
108
|
|
|
* |
109
|
|
|
* @return string A base62 representation like 6a630O1jrtMjCrQDyG3D3O |
110
|
|
|
*/ |
111
|
|
|
public function Base62() |
112
|
|
|
{ |
113
|
|
|
if (!$this->value) { |
114
|
|
|
return $this->nullValue(); |
|
|
|
|
115
|
|
|
} |
116
|
|
|
return Base62Proxy::encode($this->value); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @param string $title |
121
|
|
|
* @param array<mixed> $params |
122
|
|
|
* @return FormField|null |
123
|
|
|
*/ |
124
|
|
|
public function scaffoldFormField($title = null, $params = null) |
125
|
|
|
{ |
126
|
|
|
return null; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
public function nullValue() |
130
|
|
|
{ |
131
|
|
|
return null; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* @param mixed $value |
136
|
|
|
* @param DataObject|array<string,mixed> $record |
137
|
|
|
* @param boolean $markChanged |
138
|
|
|
* @return $this |
139
|
|
|
*/ |
140
|
|
|
public function setValue($value, $record = null, $markChanged = true) |
141
|
|
|
{ |
142
|
|
|
if ($value && is_string($value) && strlen($value) > self::BINARY_LENGTH && Uuid::isValid($value)) { |
143
|
|
|
$value = Uuid::fromString($value)->getBytes(); |
144
|
|
|
} |
145
|
|
|
return parent::setValue($value, $record, $markChanged); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @param string $value |
150
|
|
|
* @return string|null |
151
|
|
|
*/ |
152
|
|
|
public function prepValueForDB($value) |
153
|
|
|
{ |
154
|
|
|
if (!$value) { |
155
|
|
|
return $this->nullValue(); |
|
|
|
|
156
|
|
|
} |
157
|
|
|
// Uuid in string format have 36 chars |
158
|
|
|
// Strlen 16 = already binary |
159
|
|
|
if (strlen($value) === self::BINARY_LENGTH) { |
160
|
|
|
return $value; |
161
|
|
|
} |
162
|
|
|
return Uuid::fromString($value)->getBytes(); |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.