DBUuid::filterExpression()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 5
c 1
b 0
f 1
dl 0
loc 9
rs 10
cc 2
nc 2
nop 2
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();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->nullValue() targeting LeKoala\Uuid\DBUuid::nullValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->nullValue() targeting LeKoala\Uuid\DBUuid::nullValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->nullValue() targeting LeKoala\Uuid\DBUuid::nullValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->nullValue() targeting LeKoala\Uuid\DBUuid::nullValue() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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