Passed
Push — master ( d1eaf1...9deb7d )
by Kenneth
01:35
created

MySQLBindings::bStr()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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