Passed
Push — master ( b186d1...088f22 )
by Kenneth
01:35
created

MySQLBindings::bLike()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 8
c 2
b 0
f 0
nc 4
nop 3
dl 0
loc 17
rs 10
1
<?php
2
3
namespace GeekLab\GLPDO2\Bindings;
4
5
use \DomainException;
6
use \Exception;
7
use \JsonException;
8
use \PDO;
9
use GeekLab\GLPDO2\Constants;
10
11
class MySQLBindings implements BindingsInterface, Constants
12
{
13
    /**
14
     * Bind a boolean value as bool, with NULL option.
15
     *
16
     * @param int|bool|null $value
17
     * @param bool $null
18
     *
19
     * @return array
20
     * @throws Exception
21
     */
22
    public function bBool($value = null, bool $null = false): array
23
    {
24
        // use NULL
25
        if ($value === null && $null) {
26
            return $this->bStr(null, true);
27
        }
28
29
        if ($value === null && $null === false) {
30
            throw new DomainException('Can not bind NULL in boolean spot.');
31
        }
32
33
        return [(bool) $value, PDO::PARAM_BOOL];
34
    }
35
36
    /**
37
     * Bind a boolean value as int, with NULL option.
38
     *
39
     * @param int|bool|null $value
40
     * @param bool $null
41
     *
42
     * @return array
43
     * @throws Exception
44
     */
45
    public function bBoolInt($value = null, bool $null = false): array
46
    {
47
        // use NULL
48
        if ($value === null && $null) {
49
            return $this->bStr(null, true);
50
        }
51
52
        if ($value === null && $null === false) {
53
            throw new DomainException('Can not bind NULL in boolean spot.');
54
        }
55
56
        return [(int) $value, PDO::PARAM_INT];
57
    }
58
59
    /**
60
     * Bind a date value as date or optional NULL.
61
     * YYYY-MM-DD is the proper date format.
62
     *
63
     * @param string|null $value
64
     * @param bool $null
65
     *
66
     * @return array
67
     * @throws Exception
68
     */
69
    public function bDate(?string $value, bool $null = false): array
70
    {
71
        if ($value === null && !$null) {
72
            throw new DomainException('Can not bind NULL in date spot.');
73
        }
74
75
        if (empty($value) && $null) {
76
            return $this->bStr(null, true);
77
        }
78
79
        if (!empty($value)) {
80
            $value = trim($value);
81
            return $this->bStr(preg_match(self::DATE_REGEX, $value) ? $value : '1970-01-01');
82
        }
83
84
        return $this->bStr('1970-01-01');
85
    }
86
87
    /**
88
     * Bind a date value as date time or optional NULL.
89
     * YYYY-MM-DD HH:MM:SS is the proper date format.
90
     *
91
     * @param string|null $value
92
     * @param bool $null
93
     *
94
     * @return array
95
     * @throws Exception
96
     */
97
    public function bDateTime($value = null, bool $null = false): array
98
    {
99
        if ($value === null && !$null) {
100
            throw new DomainException('Can not bind NULL in date time spot.');
101
        }
102
103
        $dt = 0;
104
105
        if ($value !== null) {
106
            // Trim $value and see if it matches full date time string format.
107
            $dt = preg_match(self::DATE_TIME_REGEX, trim($value));
108
        }
109
110
        // Use NULL?
111
        if ($dt === 0 && $null) {
112
            return $this->bStr(null, true);
113
        }
114
115
        if ($dt === 0 && $value !== null) {
116
            if (preg_match(self::DATE_REGEX, $value) === 0) {
117
                // $value is not a valid date string, set to earliest date time available (GMT).
118
                $value = '1970-01-01 00:00:00';
119
            } else {
120
                // $value is a valid date string, add midnight time.
121
                $value .= ' 00:00:00';
122
            }
123
        }
124
125
        // DateTimes are really strings.
126
        return $this->bStr($value);
127
    }
128
129
    /**
130
     * Bind a float.
131
     *
132
     * @param string|int|float|null $value
133
     * @param int $decimals
134
     * @param bool $null
135
     *
136
     * @return array
137
     * @throws Exception
138
     */
139
    public function bFloat($value = null, $decimals = 3, $null = false): array
140
    {
141
        // Use NULL?
142
        if ($value === null && $null) {
143
            return $this->bRaw('NULL');
144
        }
145
146
        if ($value === null && !$null) {
147
            throw new DomainException('Can not bind NULL in float spot.');
148
        }
149
150
        if (!is_numeric($value)) {
151
            throw new DomainException('Can not bind "' . $value . '" in float spot.');
152
        }
153
154
        $format = sprintf('%%0.%df', $decimals);
155
156
        // Apparently using PDO::PARAM_STR makes this fail!
157
        return $this->bRaw(sprintf($format, $value));
158
    }
159
160
    /**
161
     * Bind an integer with optional NULL.
162
     *
163
     * @param string|int|float|bool|null $value
164
     * @param bool $null
165
     *
166
     * @return array
167
     * @throws Exception
168
     */
169
    public function bInt($value = null, bool $null = false): array
170
    {
171
        // Use NULL?
172
        if ($value === null && $null) {
173
            return $this->bStr(null, true);
174
        }
175
176
        if ($value === null && !$null) {
177
            throw new DomainException('Can not bind NULL in integer spot.');
178
        }
179
180
        if (!is_numeric($value)) {
181
            throw new DomainException('Can not bind "' . $value . '" in integer spot.');
182
        }
183
184
        return [(int) sprintf('%u', $value), PDO::PARAM_INT];
185
    }
186
187
    /**
188
     * Convert array of integers to comma separated values. Uses %%
189
     * Great for IN() statements.
190
     *
191
     * @param array $data
192
     * @param int $default
193
     *
194
     * @return array
195
     * @throws Exception
196
     */
197
    public function bIntArray(array $data, int $default = 0): array
198
    {
199
        if (empty($data)) {
200
            throw new DomainException('Can not bind an empty array.');
201
        }
202
203
        // Make unique integer array
204
        $numbers = array();
205
206
        foreach ($data as $value) {
207
            $numbers[(int) $value] = true;
208
        }
209
210
        $numbers = array_keys($numbers);
211
212
        // turn into a string
213
        $result = implode(', ', $numbers);
214
215
        return $this->bRaw($result ?: $default);
216
    }
217
218
    /**
219
     * Bind a object or JSON string to a string
220
     *
221
     * @param string|object|null $value
222
     * @param bool $null
223
     *
224
     * @return array
225
     * @throws \JsonException
226
     */
227
    public function bJSON($value, bool $null = false): array
228
    {
229
        // Use NULL?
230
        if ($value === null && $null) {
231
            return $this->bStr(null, true);
232
        }
233
234
        if ($value === null && !$null) {
235
            throw new DomainException('Can not bind NULL in JSON spot.');
236
        }
237
238
        if (is_object($value)) {
239
            $value = json_encode($value);
240
        } elseif (is_string($value)) {
241
            $JSON = json_decode($value, false, 255);
242
243
            if (json_last_error()) {
244
                throw new JsonException('Can not bind invalid JSON in JSON spot. (' . json_last_error_msg() . ')');
245
            }
246
247
            $value = json_encode($JSON);
248
        } else {
249
            throw new JsonException('Can not bind invalid JSON in JSON spot. (' . $value . ')');
250
        }
251
252
        return $this->bStr($value);
253
    }
254
255
    /**
256
     * Create and bind string for LIKE() statements.
257
     *
258
     * @param string $value
259
     * @param bool $ends Ends with?
260
     * @param bool $starts Starts with?
261
     *
262
     * @return array
263
     */
264
    public function bLike(string $value, bool $ends = false, bool $starts = false): array
265
    {
266
        // Convert start and end options into a 2 bit binary. 00, 01, 10, 11.
267
        $binValue = ($starts * 1) + ($ends * 2);
268
269
        if ($binValue === 1) {
270
            // Starts with.
271
            $value .= '%';
272
        } elseif ($binValue === 2) {
273
            // Ends with.
274
            $value = '%' . $value;
275
        } elseif ($binValue === 0) {
276
            // Is somewhere...
277
            $value = '%' . $value . '%';
278
        }
279
280
        return [$value];
281
    }
282
283
    /**
284
     * !!!DANGER!!!
285
     * Bind a raw value.
286
     *
287
     * @param string|int|float|bool $value
288
     *
289
     * @return array
290
     */
291
    public function bRaw($value): array
292
    {
293
        return [$value];
294
    }
295
296
    /**
297
     * Bind a string value.
298
     *
299
     * @param string|int|float|bool|null $value
300
     * @param bool $null
301
     * @param int $type
302
     *
303
     * @return array
304
     * @throws Exception
305
     */
306
    public function bStr($value, bool $null = false, int $type = PDO::PARAM_STR): array
307
    {
308
        //$name = $this->getNextName();
309
310
        if ($value === null && $null) {
311
            $type = PDO::PARAM_NULL;
312
        } elseif ($value === null && !$null) {
313
            throw new DomainException('Can not bind NULL in string spot.');
314
        }
315
316
        return [(string) $value, $type];
317
    }
318
319
    /**
320
     * Convert an array into a string and bind it.
321
     * Great for IN() statements.
322
     *
323
     * @param array $values
324
     * @param string|int|float|bool $default
325
     *
326
     * @return array
327
     */
328
    public function bStrArr(array $values, $default = ''): array
329
    {
330
        //  No array elements?
331
        $aStr = empty($values) ? $default : '\'' . implode("', '", $values) . '\'';
332
333
        return $this->bRaw($aStr);
334
    }
335
}
336