Passed
Push — master ( f71b04...7dcb0c )
by P.R.
12:30
created

MySqlDataTypeHelper::escapePhpExpression()   D

Complexity

Conditions 32
Paths 32

Size

Total Lines 64
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 32
eloc 51
nc 32
nop 2
dl 0
loc 64
rs 4.1666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace SetBased\Stratum\MySql\Loader\Helper;
5
6
use SetBased\Exception\FallenException;
7
use SetBased\Stratum\Common\Helper\CommonDataTypeHelper;
8
9
/**
10
 * Utility class for deriving information based on a MySQL data type.
11
 */
12
class MySqlDataTypeHelper implements CommonDataTypeHelper
13
{
14
  //--------------------------------------------------------------------------------------------------------------------
15
  /**
16
   * Returns the widths of a field based on a MySQL data type.
17
   *
18
   * @param array $dataTypeInfo Metadata of the column on which the field is based.
19
   */
20
  public static function deriveFieldLength(array $dataTypeInfo): ?int
21
  {
22
    switch ($dataTypeInfo['data_type'])
23
    {
24
      case 'tinyint':
25
      case 'smallint':
26
      case 'mediumint':
27
      case 'int':
28
      case 'bigint':
29
      case 'float':
30
      case 'double':
31
        $ret = $dataTypeInfo['numeric_precision'];
32
        break;
33
34
      case 'decimal':
35
        $ret = $dataTypeInfo['numeric_precision'];
36
        if ($dataTypeInfo['numeric_scale']>0)
37
        {
38
          $ret += 1;
39
        }
40
        break;
41
42
      case 'char':
43
      case 'varchar':
44
      case 'binary':
45
      case 'varbinary':
46
      case 'tinytext':
47
      case 'text':
48
      case 'mediumtext':
49
      case 'longtext':
50
      case 'tinyblob':
51
      case 'blob':
52
      case 'mediumblob':
53
      case 'longblob':
54
      case 'bit':
55
      case 'json':
56
        $ret = $dataTypeInfo['character_maximum_length'];
57
        break;
58
59
      case 'datetime':
60
      case 'timestamp':
61
        $ret = 16;
62
        break;
63
64
      case 'inet4':
65
        $ret = 15;
66
        break;
67
68
      case 'inet6':
69
        // Fully written out IPv4 mapped addresses are not supported.
70
        $ret = 39;
71
        break;
72
73
      case 'year':
74
        $ret = 4;
75
        break;
76
77
      case 'time':
78
        $ret = 8;
79
        break;
80
81
      case 'date':
82
        $ret = 10;
83
        break;
84
85
      case 'enum':
86
      case 'set':
87
        // We don't assign a width to column with type enum and set.
88
        $ret = null;
89
        break;
90
91
      default:
92
        throw new FallenException('data type', $dataTypeInfo['data_type']);
93
    }
94
95
    return $ret;
96
  }
97
98
  //--------------------------------------------------------------------------------------------------------------------
99
  /**
100
   * Returns the type of bind variable.
101
   *
102
   * @see http://php.net/manual/en/mysqli-stmt.bind-param.php
103
   *
104
   * @param array $dataTypeInfo Metadata of the column on which the field is based.
105
   */
106
  public static function getBindVariableType(array $dataTypeInfo): string
107
  {
108
    $ret = '';
109
    switch ($dataTypeInfo['data_type'])
110
    {
111
      case 'tinyint':
112
      case 'smallint':
113
      case 'mediumint':
114
      case 'int':
115
      case 'bigint':
116
      case 'year':
117
        $ret = 'i';
118
        break;
119
120
      case 'float':
121
      case 'double':
122
        $ret = 'd';
123
        break;
124
125
      case 'time':
126
      case 'timestamp':
127
      case 'binary':
128
      case 'enum':
129
      case 'bit':
130
      case 'set':
131
      case 'char':
132
      case 'varchar':
133
      case 'date':
134
      case 'datetime':
135
      case 'varbinary':
136
      case 'decimal':
137
      case 'inet4':
138
      case 'inet6':
139
      case 'list_of_int':
140
        $ret = 's';
141
        break;
142
143
      case 'tinytext':
144
      case 'text':
145
      case 'mediumtext':
146
      case 'longtext':
147
      case 'tinyblob':
148
      case 'blob':
149
      case 'mediumblob':
150
      case 'longblob':
151
        $ret .= 'b';
152
        break;
153
154
      default:
155
        throw new FallenException('parameter type', $dataTypeInfo['data_type']);
156
    }
157
158
    return $ret;
159
  }
160
161
  //--------------------------------------------------------------------------------------------------------------------
162
  /**
163
   * Returns whether MySQL column type is a BLOB or a CLOB.
164
   *
165
   * @param string $dataType Metadata of the MySQL data type.
166
   */
167
  public static function isBlobParameter(string $dataType): bool
168
  {
169
    switch ($dataType)
170
    {
171
      case 'tinytext':
172
      case 'text':
173
      case 'mediumtext':
174
      case 'longtext':
175
      case 'tinyblob':
176
      case 'blob':
177
      case 'mediumblob':
178
      case 'longblob':
179
        $isBlob = true;
180
        break;
181
182
      case 'tinyint':
183
      case 'smallint':
184
      case 'mediumint':
185
      case 'int':
186
      case 'bigint':
187
      case 'year':
188
      case 'decimal':
189
      case 'float':
190
      case 'double':
191
      case 'time':
192
      case 'timestamp':
193
      case 'binary':
194
      case 'enum':
195
      case 'inet4':
196
      case 'inet6':
197
      case 'bit':
198
      case 'set':
199
      case 'char':
200
      case 'varchar':
201
      case 'date':
202
      case 'datetime':
203
      case 'varbinary':
204
      case 'list_of_int':
205
        $isBlob = false;
206
        break;
207
208
      default:
209
        throw new FallenException('data type', $dataType);
210
    }
211
212
    return $isBlob;
213
  }
214
215
  //--------------------------------------------------------------------------------------------------------------------
216
  /**
217
   * Returns the corresponding PHP type declaration of a MySQL column type.
218
   *
219
   * @param string $phpTypeHint The PHP type hinting.
220
   */
221
  public static function phpTypeHintingToPhpTypeDeclaration(string $phpTypeHint): string
222
  {
223
    $phpType = '';
224
225
    switch ($phpTypeHint)
226
    {
227
      case 'array':
228
      case 'array[]':
229
      case 'bool':
230
      case 'float':
231
      case 'int':
232
      case 'string':
233
      case 'void':
234
        $phpType = $phpTypeHint;
235
        break;
236
237
      case 'int[]':
238
        $phpType = 'array';
239
        break;
240
241
      default:
242
        $parts = explode('|', $phpTypeHint);
243
        $key   = array_search('null', $parts);
244
        if (sizeof($parts)===2 && $key!==false)
245
        {
246
          unset($parts[$key]);
247
248
          $tmp = static::phpTypeHintingToPhpTypeDeclaration(implode('|', $parts));
249
          if ($tmp!=='')
250
          {
251
            $phpType = '?'.$tmp;
252
          }
253
        }
254
    }
255
256
    return $phpType;
257
  }
258
259
  //--------------------------------------------------------------------------------------------------------------------
260
  /**
261
   * @inheritdoc
262
   */
263
  public function allColumnTypes(): array
264
  {
265
    return ['int',
266
            'smallint',
267
            'tinyint',
268
            'mediumint',
269
            'bigint',
270
            'decimal',
271
            'float',
272
            'double',
273
            'bit',
274
            'date',
275
            'datetime',
276
            'timestamp',
277
            'time',
278
            'year',
279
            'char',
280
            'varchar',
281
            'binary',
282
            'varbinary',
283
            'enum',
284
            'set',
285
            'inet4',
286
            'inet6',
287
            'tinyblob',
288
            'blob',
289
            'mediumblob',
290
            'longblob',
291
            'tinytext',
292
            'text',
293
            'mediumtext',
294
            'longtext'];
295
  }
296
297
  //--------------------------------------------------------------------------------------------------------------------
298
  /**
299
   * Returns the corresponding PHP type hinting of a MySQL column type.
300
   *
301
   * @param string[] $dataTypeInfo Metadata of the MySQL data type.
302
   */
303
  public function columnTypeToPhpType(array $dataTypeInfo): string
304
  {
305
    switch ($dataTypeInfo['data_type'])
306
    {
307
      case 'tinyint':
308
      case 'smallint':
309
      case 'mediumint':
310
      case 'int':
311
      case 'bigint':
312
      case 'year':
313
        $phpType = 'int';
314
        break;
315
316
      case 'decimal':
317
        $phpType = 'int|float|string';
318
        break;
319
320
      case 'float':
321
      case 'double':
322
        $phpType = 'float';
323
        break;
324
325
      case 'bit':
326
      case 'varbinary':
327
      case 'binary':
328
      case 'char':
329
      case 'varchar':
330
      case 'time':
331
      case 'timestamp':
332
      case 'date':
333
      case 'datetime':
334
      case 'enum':
335
      case 'inet4':
336
      case 'inet6':
337
      case 'set':
338
      case 'tinytext':
339
      case 'text':
340
      case 'mediumtext':
341
      case 'longtext':
342
      case 'tinyblob':
343
      case 'blob':
344
      case 'mediumblob':
345
      case 'longblob':
346
        $phpType = 'string';
347
        break;
348
349
      case 'list_of_int':
350
        $phpType = 'array|string';
351
        break;
352
353
      default:
354
        throw new FallenException('data type', $dataTypeInfo['data_type']);
355
    }
356
357
    return $phpType;
358
  }
359
360
  //--------------------------------------------------------------------------------------------------------------------
361
  /**
362
   * Returns PHP code escaping the value of a PHP expression that can be safely used when concatenating a SQL statement.
363
   *
364
   * @param array  $dataTypeInfo Metadata of the column on which the field is based.
365
   * @param string $expression   The PHP expression.
366
   */
367
  public function escapePhpExpression(array $dataTypeInfo, string $expression): string
368
  {
369
    switch ($dataTypeInfo['data_type'])
370
    {
371
      case 'tinyint':
372
      case 'smallint':
373
      case 'mediumint':
374
      case 'int':
375
      case 'bigint':
376
      case 'year':
377
        $ret = "'.\$this->quoteInt(".$expression.").'";
378
        break;
379
380
      case 'float':
381
      case 'double':
382
        $ret = "'.\$this->quoteFloat(".$expression.").'";
383
        break;
384
385
      case 'char':
386
      case 'varchar':
387
      case 'time':
388
      case 'timestamp':
389
      case 'date':
390
      case 'datetime':
391
      case 'enum':
392
      case 'inet4':
393
      case 'inet6':
394
      case 'set':
395
        $ret = "'.\$this->quoteString(".$expression.").'";
396
        break;
397
398
      case 'binary':
399
      case 'varbinary':
400
        $ret = "'.\$this->quoteBinary(".$expression.").'";
401
        break;
402
403
      case 'decimal':
404
        $ret = "'.\$this->quoteDecimal(".$expression.").'";
405
        break;
406
407
      case 'bit':
408
        $ret = "'.\$this->quoteBit(".$expression.").'";
409
        break;
410
411
      case 'tinytext':
412
      case 'text':
413
      case 'mediumtext':
414
      case 'longtext':
415
      case 'tinyblob':
416
      case 'blob':
417
      case 'mediumblob':
418
      case 'longblob':
419
        $ret = '?';
420
        break;
421
422
      case 'list_of_int':
423
        $ret = "'.\$this->quoteListOfInt(".$expression.", '".addslashes($dataTypeInfo['delimiter'])."', '".addslashes($dataTypeInfo['enclosure'])."', '".addslashes($dataTypeInfo['escape'])."').'";
424
        break;
425
426
      default:
427
        throw new FallenException('data type', $dataTypeInfo['data_type']);
428
    }
429
430
    return $ret;
431
  }
432
433
  //--------------------------------------------------------------------------------------------------------------------
434
}
435
436
//----------------------------------------------------------------------------------------------------------------------
437