Passed
Push — master ( 6db175...709bfd )
by y
01:41
created

StrTrait::toBase10()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Helix\DB\Fluent\Str;
4
5
use Helix\DB\Fluent\Num;
6
use Helix\DB\Fluent\Num\BaseConversionTrait;
7
use Helix\DB\Fluent\Predicate;
8
use Helix\DB\Fluent\Str;
9
use Helix\DB\Fluent\Value\ValueTrait;
10
use Helix\DB\Fluent\ValueInterface;
11
12
/**
13
 * Character string expression manipulation.
14
 */
15
trait StrTrait
16
{
17
18
    use ValueTrait;
19
    use BaseConversionTrait;
20
21
    /**
22
     * @param int $direction
23
     * @param null|string $chars
24
     * @return Str
25
     * @internal
26
     */
27
    protected function _trim(int $direction, string $chars = null)
28
    {
29
        $function = [-1 => 'LTRIM', 0 => 'TRIM', 1 => 'RTRIM'][$direction];
30
        if (isset($chars)) {
31
            $chars = $this->db->quote($chars);
32
            if ($this->db->isSQLite()) {
33
                return Str::factory($this->db, "{$function}({$this},{$chars})");
34
            }
35
            $direction = [-1 => 'LEADING', 0 => 'BOTH', 1 => 'TRAILING'][$direction];
36
            return Str::factory($this->db, "TRIM({$direction} {$chars} FROM {$this})");
37
        }
38
        return Str::factory($this->db, "{$function}({$this})");
39
    }
40
41
    /**
42
     * Concatenate other strings.
43
     *
44
     * @param string|ValueInterface ...$strings
45
     * @return Str
46
     */
47
    public function concat(...$strings)
48
    {
49
        array_unshift($strings, $this);
50
        $strings = $this->db->quoteArray($strings);
51
        if ($this->db->isSQLite()) {
52
            return Str::factory($this->db, sprintf('(%s)', implode(' || ', $strings)));
53
        }
54
        return Str::factory($this->db, sprintf('CONCAT(%s)', implode(',', $strings)));
55
    }
56
57
    /**
58
     * Hex representation.
59
     *
60
     * @return Str
61
     */
62
    public function hex()
63
    {
64
        return Str::factory($this->db, "HEX({$this})");
65
    }
66
67
    /**
68
     * Zero-length.
69
     *
70
     * @return Predicate
71
     */
72
    public function isEmpty()
73
    {
74
        return $this->length()->isZero();
75
    }
76
77
    /**
78
     * Number of characters (not necessarily bytes).
79
     *
80
     * @see StrTrait::size()
81
     *
82
     * @return Num
83
     */
84
    public function length()
85
    {
86
        return Num::fromFormat($this->db, [
87
            'mysql' => "CHAR_LENGTH(%s)",
88
            'sqlite' => "LENGTH(CAST(%s AS TEXT))"
89
        ], $this);
90
    }
91
92
    /**
93
     * Lowercase.
94
     *
95
     * @return Str
96
     */
97
    public function lower()
98
    {
99
        return Str::factory($this->db, "LOWER({$this})");
100
    }
101
102
    /**
103
     * See {@link StrTrait::trim()}
104
     *
105
     * @param null|string $chars
106
     * @return Str
107
     */
108
    public function ltrim(string $chars = null)
109
    {
110
        return $this->_trim(-1, $chars);
111
    }
112
113
    /**
114
     * Substring's position (1-based).
115
     *
116
     * The position is `0` if the substring isn't found.
117
     *
118
     * @param string $substring
119
     * @return Num
120
     */
121
    public function position(string $substring)
122
    {
123
        $substring = $this->db->quote($substring);
124
        if ($this->db->isSQLite()) {
125
            return Num::factory($this->db, "INSTR({$this},{$substring})");
126
        }
127
        return Num::factory($this->db, "LOCATE({$substring},{$this})");
128
    }
129
130
    /**
131
     * String replacement.
132
     *
133
     * @param string $search
134
     * @param string $replace
135
     * @return Str
136
     */
137
    public function replace(string $search, string $replace)
138
    {
139
        $search = $this->db->quote($search);
140
        $replace = $this->db->quote($replace);
141
        return Str::factory($this->db, "REPLACE({$this},{$search},{$replace})");
142
    }
143
144
    /**
145
     * See {@link StrTrait::trim()}
146
     *
147
     * @param null|string $chars
148
     * @return Str
149
     */
150
    public function rtrim(string $chars = null)
151
    {
152
        return $this->_trim(1, $chars);
153
    }
154
155
    /**
156
     * Number of bytes (not necessarily characters).
157
     *
158
     * @return Num
159
     */
160
    public function size()
161
    {
162
        return Num::fromFormat($this->db, [
163
            'mysql' => "LENGTH(%s)",
164
            'sqlite' => "LENGTH(CAST(%s AS BLOB))"
165
        ], $this);
166
    }
167
168
    /**
169
     * Substring.
170
     *
171
     * @param int $start 1-based, can be negative to start from the right.
172
     * @param null|int $length
173
     * @return Str
174
     */
175
    public function substr(int $start, int $length = null)
176
    {
177
        assert($start !== 0);
178
        if (isset($length)) {
179
            return Str::factory($this->db, "SUBSTR({$this},{$start},{$length})");
180
        }
181
        return Str::factory($this->db, "SUBSTR({$this},{$start})");
182
    }
183
184
    /**
185
     * Convert from an arbitrary base to base 10.
186
     *
187
     * @param int $from
188
     * @return Num
189
     */
190
    public function toBase10(int $from)
191
    {
192
        return Num::factory($this->db, "CONV({$this},{$from},10)");
193
    }
194
195
    /**
196
     * Trims whitespace (or other things) from both ends of the string.
197
     *
198
     * If `$chars` is given:
199
     * - MySQL treats it as a leading/trailing string
200
     * - SQLite treats it as individual characters (same as PHP)
201
     *
202
     * @see StrTrait::ltrim()
203
     * @see StrTrait::rtrim()
204
     *
205
     * @param null|string $chars
206
     * @return Str
207
     */
208
    public function trim(string $chars = null)
209
    {
210
        return $this->_trim(0, $chars);
211
    }
212
213
    /**
214
     * Uppercase.
215
     *
216
     * @return Str
217
     */
218
    public function upper()
219
    {
220
        return Str::factory($this->db, "UPPER({$this})");
221
    }
222
}
223