Passed
Push — master ( 54cddc...ce0b50 )
by Thomas
23:37 queued 11:26
created

DBUuid::filterExpression()   A

Complexity

Conditions 2
Paths 2

Size

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