Completed
Push — master ( a7e144...4cf57b )
by Daniel
04:19
created

MySQLiByDanielGP   D

Complexity

Total Complexity 116

Size/Duplication

Total Lines 793
Duplicated Lines 5.42 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 19
Bugs 0 Features 3
Metric Value
wmc 116
c 19
b 0
f 3
lcom 2
cbo 3
dl 43
loc 793
rs 4.4444

25 Methods

Rating   Name   Duplication   Size   Complexity  
B listOfMySQLqueryLanguageType() 0 39 1
B listOfMySQLqueryStatementType() 0 154 1
A connectToMySql() 0 15 3
A getMySQLactiveDatabases() 0 4 1
A getMySQLactiveEngines() 0 4 1
A getMySQLgenericInformations() 0 12 2
A getMySQLglobalVariables() 0 4 1
A getMySQLlistColumns() 0 4 1
A getMySQLlistDatabases() 0 4 1
A getMySQLlistEngines() 0 4 1
A getMySQLlistIndexes() 0 4 1
C getMySQLlistMultiple() 0 45 11
A getMySQLStatistics() 0 4 1
A getMySQLlistTables() 0 4 1
A getMySQLqueryType() 0 23 2
A getMySQLqueryWithParameterIdentifier() 0 8 2
A getMySQLserverTime() 0 4 1
A stFldLmts() 0 8 2
A getRowDataFromTable() 0 12 3
C setArrayToFilterValues() 0 40 14
A stFldLmtsExact() 0 15 2
A setFieldNumbers() 0 12 4
B setFieldSpecific() 0 18 7
C setMySQLquery2Server() 19 70 19
D setMySQLquery2ServerByPattern() 24 120 33

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like MySQLiByDanielGP often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MySQLiByDanielGP, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 *
5
 * The MIT License (MIT)
6
 *
7
 * Copyright (c) 2015 Daniel Popiniuc
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
29
namespace danielgp\common_lib;
30
31
/**
32
 * Usefull functions to get quick MySQL content
33
 *
34
 * @author Daniel Popiniuc
35
 */
36
trait MySQLiByDanielGP
37
{
38
39
    use DomComponentsByDanielGP,
40
        MySQLiMultiple,
41
        MySQLiByDanielGPqueries;
42
43
    /**
44
     * Intiates connection to MySQL
45
     *
46
     * @param array $mySQLconfig
47
     *
48
     * $mySQLconfig           = [
49
     * 'host'     => MYSQL_HOST,
50
     * 'port'     => MYSQL_PORT,
51
     * 'username' => MYSQL_USERNAME,
52
     * 'password' => MYSQL_PASSWORD,
53
     * 'database' => MYSQL_DATABASE,
54
     * ];
55
     */
56
    protected function connectToMySql($mySQLconfig)
57
    {
58
        if (is_null($this->mySQLconnection)) {
59
            extract($mySQLconfig);
60
            $this->mySQLconnection = new \mysqli($host, $username, $password, $database, $port);
61
            if (is_null($this->mySQLconnection->connect_error)) {
62
                return '';
63
            }
64
            $erNo                  = $this->mySQLconnection->connect_errno;
65
            $erMsg                 = $this->mySQLconnection->connect_error;
66
            $this->mySQLconnection = null;
67
            $msg                   = $this->lclMsgCmn('i18n_Feedback_ConnectionError');
68
            return sprintf($msg, $erNo, $erMsg, $host, $port, $username, $database);
69
        }
70
    }
71
72
    /**
73
     * returns a list of MySQL databases
74
     *
75
     * @return array
76
     */
77
    protected function getMySQLactiveDatabases()
78
    {
79
        return $this->getMySQLlistDatabases(true);
80
    }
81
82
    /**
83
     * returns a list of active MySQL engines
84
     *
85
     * @return array
86
     */
87
    protected function getMySQLactiveEngines()
88
    {
89
        return $this->getMySQLlistEngines(true);
90
    }
91
92
    /**
93
     * returns the list of all MySQL generic informations
94
     *
95
     * @return array
96
     */
97
    protected function getMySQLgenericInformations()
98
    {
99
        if (is_null($this->mySQLconnection)) {
100
            $line = [];
101
        } else {
102
            $line = [
103
                'Info'    => $this->mySQLconnection->server_info,
104
                'Version' => $this->mySQLconnection->server_version
105
            ];
106
        }
107
        return $line;
108
    }
109
110
    /**
111
     * returns the list of all MySQL global variables
112
     *
113
     * @return array
114
     */
115
    protected function getMySQLglobalVariables()
116
    {
117
        return $this->getMySQLlistMultiple('VariablesGlobal', 'array_key_value');
118
    }
119
120
    /**
121
     * returns a list of MySQL indexes (w. choice of to choose any combination of db/table/column)
122
     *
123
     * @return array
124
     */
125
    protected function getMySQLlistColumns($filterArray = null)
126
    {
127
        return $this->getMySQLlistMultiple('Columns', 'full_array_key_numbered', $filterArray);
128
    }
129
130
    /**
131
     * returns a list of MySQL databases (w. choice of exclude/include the system ones)
132
     *
133
     * @return array
134
     */
135
    protected function getMySQLlistDatabases($excludeSystemDbs = true)
136
    {
137
        return $this->getMySQLlistMultiple('Databases', 'array_first_key_rest_values', $excludeSystemDbs);
138
    }
139
140
    /**
141
     * returns a list of MySQL engines (w. choice of return only the active ones)
142
     *
143
     * @return array
144
     */
145
    protected function getMySQLlistEngines($onlyActiveOnes = true)
146
    {
147
        return $this->getMySQLlistMultiple('Engines', 'array_first_key_rest_values', $onlyActiveOnes);
148
    }
149
150
    /**
151
     * returns a list of MySQL indexes (w. choice of to choose any combination of db/table/column)
152
     *
153
     * @return array
154
     */
155
    protected function getMySQLlistIndexes($filterArray = null)
156
    {
157
        return $this->getMySQLlistMultiple('Indexes', 'full_array_key_numbered', $filterArray);
158
    }
159
160
    /**
161
     * Return various informations (from predefined list) from the MySQL server
162
     *
163
     * @return string
164
     */
165
    private function getMySQLlistMultiple($returnChoice, $returnType, $additionalFeatures = null)
166
    {
167
        if (is_null($this->mySQLconnection)) {
168
            switch ($returnType) {
169
                case 'value':
170
                    $line = null;
171
                    break;
172
                default:
173
                    $line = [];
174
                    break;
175
            }
176
        } else {
177
            $query = '';
178
            switch ($returnChoice) {
179
                case 'Columns':
180
                    $query = $this->sQueryMySqlColumns($additionalFeatures);
181
                    break;
182
                case 'Databases':
183
                    $query = $this->sQueryMySqlActiveDatabases($additionalFeatures);
184
                    break;
185
                case 'Engines':
186
                    $query = $this->sQueryMySqlActiveEngines($additionalFeatures);
187
                    break;
188
                case 'Indexes':
189
                    $query = $this->sQueryMySqlIndexes($additionalFeatures);
190
                    break;
191
                case 'ServerTime':
192
                    $query = $this->sQueryMySqlServerTime();
193
                    break;
194
                case 'Statistics':
195
                    $query = $this->sQueryMySqlStatistics($additionalFeatures);
196
                    break;
197
                case 'Tables':
198
                    $query = $this->sQueryMySqlTables($additionalFeatures);
199
                    break;
200
                case 'VariablesGlobal':
201
                    $query = $this->sQueryMySqlGlobalVariables();
202
                    break;
203
            }
204
            $line = $this->setMySQLquery2Server($query, $returnType)[
205
                    'result'
206
            ];
207
        }
208
        return $line;
209
    }
210
211
    /**
212
     * Return the list of Tables from the MySQL server
213
     *
214
     * @return string
215
     */
216
    protected function getMySQLStatistics($filterArray = null)
217
    {
218
        return $this->getMySQLlistMultiple('Statistics', 'full_array_key_numbered', $filterArray);
219
    }
220
221
    /**
222
     * Return the list of Tables from the MySQL server
223
     *
224
     * @return string
225
     */
226
    protected function getMySQLlistTables($filterArray = null)
227
    {
228
        return $this->getMySQLlistMultiple('Tables', 'full_array_key_numbered', $filterArray);
229
    }
230
231
    /**
232
     * Returns the Query language type by scanning the 1st keyword from a given query
233
     *
234
     * @param input $sQuery
235
     */
236
    protected function getMySQLqueryType($sQuery)
237
    {
238
        $queryPieces    = explode(' ', $sQuery);
239
        $statementTypes = $this->getMySQLqueryStatementType();
0 ignored issues
show
Bug introduced by
It seems like getMySQLqueryStatementType() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
240
        if (in_array($queryPieces[0], array_keys($statementTypes))) {
241
            $type    = $statementTypes[$queryPieces[0]]['Type'];
242
            $sReturn = array_merge([
243
                'detected1stKeywordWithinQuery' => $queryPieces[0],
244
                $type                           => $this->getMySQLqueryLanguageType()[$type],
0 ignored issues
show
Bug introduced by
It seems like getMySQLqueryLanguageType() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
245
                    ], $statementTypes[$queryPieces[0]]);
246
        } else {
247
            $sReturn = [
248
                'detected1stKeywordWithinQuery' => $queryPieces[0],
249
                'unknown'                       => [
250
                    'standsFor'   => 'unknown',
251
                    'description' => 'unknown',
252
                ],
253
                'Type'                          => 'unknown',
254
                'Description'                   => 'unknown',
255
            ];
256
        }
257
        return $sReturn;
258
    }
259
260
    /**
261
     * Provides a detection if given Query does contain a Parameter
262
     * that may require statement processing later on
263
     *
264
     * @param string $sQuery
265
     * @param string $paramIdentifier
266
     * @return boolean
267
     */
268
    protected function getMySQLqueryWithParameterIdentifier($sQuery, $paramIdentifier)
269
    {
270
        $sReturn = true;
271
        if (strpos($sQuery, $paramIdentifier) === false) {
272
            $sReturn = false;
273
        }
274
        return $sReturn;
275
    }
276
277
    /**
278
     * Return the time from the MySQL server
279
     *
280
     * @return string
281
     */
282
    protected function getMySQLserverTime()
283
    {
284
        return $this->getMySQLlistMultiple('ServerTime', 'value');
285
    }
286
287
    /**
288
     * Reads data from table into REQUEST super global
289
     *
290
     * @param string $tableName
291
     * @param array $filtersArray
292
     */
293
    protected function getRowDataFromTable($tableName, $filtersArray)
294
    {
295
        $query   = $this->sQueryRowsFromTable([$tableName, $this->setArrayToFilterValues($filtersArray)]);
296
        $rawData = $this->setMySQLquery2Server($query, 'array_pairs_key_value')['result'];
297
        if (!is_null($rawData)) {
298
            $this->initializeSprGlbAndSession();
299
            foreach ($rawData as $key => $value) {
300
                $vToSet = str_replace(['\\\\"', '\\"', "\\\\'", "\\'"], ['"', '"', "'", "'"], $value);
301
                $this->tCmnRequest->request->get($key, $vToSet);
302
            }
303
        }
304
    }
305
306
    /**
307
     * Just to keep a list of type of language as array
308
     *
309
     * @return array
310
     */
311
    private static function listOfMySQLqueryLanguageType()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
312
    {
313
        return [
314
            'DCL' => [
315
                'standsFor'   => 'Data Control Language',
316
                'description' => implode(', ', [
317
                    'includes commands such as GRANT',
318
                    'and mostly concerned with rights',
319
                    'permissions and other controls of the database system',
320
                ]),
321
            ],
322
            'DDL' => [
323
                'standsFor'   => 'Data Definition Language',
324
                'description' => implode(', ', [
325
                    'deals with database schemas and descriptions',
326
                    'of how the data should reside in the database',
327
                ]),
328
            ],
329
            'DML' => [
330
                'standsFor'   => 'Data Manipulation Language',
331
                'description' => implode(', ', [
332
                    'deals with data manipulation',
333
                    'and includes most common SQL statements such as SELECT, INSERT, UPDATE, DELETE etc',
334
                    'and it is used to store, modify, retrieve, delete and update data in database',
335
                ]),
336
            ],
337
            'DQL' => [
338
                'standsFor'   => 'Data Query Language',
339
                'description' => 'deals with data/structure retrieval',
340
            ],
341
            'DTL' => [
342
                'standsFor'   => 'Data Transaction Language',
343
                'description' => implode('. ', [
344
                    'statements are used to manage changes made by DML statements',
345
                    'It allows statements to be grouped together into logical transactions',
346
                ]),
347
            ],
348
        ];
349
    }
350
351
    /**
352
     * Just to keep a list of statement types as array
353
     *
354
     * @return array
355
     */
356
    private static function listOfMySQLqueryStatementType()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
357
    {
358
        return [
359
            'ALTER'     => [
360
                'Type'        => 'DDL',
361
                'Description' => 'create objects in the database',
362
            ],
363
            'CALL'      => [
364
                'Type'        => 'DML',
365
                'Description' => 'call a stored procedure',
366
            ],
367
            'COMMENT'   => [
368
                'Type'        => 'DDL',
369
                'Description' => 'add comments to the data dictionary',
370
            ],
371
            'COMMIT'    => [
372
                'Type'        => 'DTL',
373
                'Description' => 'sends a signal to MySQL to save all un-commited statements',
374
            ],
375
            'CREATE'    => [
376
                'Type'        => 'DDL',
377
                'Description' => 'create objects within a database',
378
            ],
379
            'DELETE'    => [
380
                'Type'        => 'DML',
381
                'Description' => 'deletes records from a table (all or partial depending on potential conditions)',
382
            ],
383
            'DESC'      => [
384
                'Type'        => 'DML',
385
                'Description' => 'interpretation of the data access path (synonym of EXPLAIN)',
386
            ],
387
            'DESCRIBE'  => [
388
                'type'        => 'DML',
389
                'Description' => 'interpretation of the data access path (synonym of EXPLAIN)',
390
            ],
391
            'DO'        => [
392
                'Type'        => 'DML',
393
                'Description' => 'executes an expression without returning any result',
394
            ],
395
            'DROP'      => [
396
                'Type'        => 'DDL',
397
                'Description' => 'delete objects from a database',
398
            ],
399
            'EXPLAIN'   => [
400
                'Type'        => 'DML',
401
                'Description' => 'interpretation of the data access path',
402
            ],
403
            'GRANT'     => [
404
                'Type'        => 'DCL',
405
                'Description' => 'allow users access privileges to database',
406
            ],
407
            'HANDLER'   => [
408
                'Type'        => 'DML',
409
                'Description' => 'statement provides direct access to table storage engine interfaces',
410
            ],
411
            'HELP'      => [
412
                'Type'        => 'DQL',
413
                'Description' => implode(' ', [
414
                    'The HELP statement returns online information from the MySQL Reference manual.',
415
                    'Its proper operation requires that the help tables in the mysql database',
416
                    'be initialized with help topic information',
417
                ]),
418
            ],
419
            'INSERT'    => [
420
                'Type'        => 'DML',
421
                'Description' => 'insert data into a table',
422
            ],
423
            'LOAD'      => [
424
                'Type'        => 'DML',
425
                'Description' => implode(' ', [
426
                    'The LOAD DATA INFILE statement reads rows from a text file',
427
                    'into a table at a very high speed',
428
                    'or LOAD XML statement reads data from an XML file into a table',
429
                ]),
430
            ],
431
            'LOCK'      => [
432
                'Type'        => 'DML',
433
                'Description' => 'concurrency control',
434
            ],
435
            'MERGE'     => [
436
                'Type'        => 'DML',
437
                'Description' => 'UPSERT operation (insert or update)',
438
            ],
439
            'RELEASE'   => [
440
                'Type'        => 'DTL',
441
                'Description' => implode(' ', [
442
                    'The RELEASE SAVEPOINT statement removes the named savepoint',
443
                    'from the set of savepoints of the current transaction.',
444
                    'No commit or rollback occurs. It is an error if the savepoint does not exist.',
445
                ]),
446
            ],
447
            'RENAME'    => [
448
                'Type'        => 'DDL',
449
                'Description' => 'rename objects from a database',
450
            ],
451
            'REPLACE'   => [
452
                'Type'        => 'DML',
453
                'Description' => implode(' ', [
454
                    'REPLACE works exactly like INSERT, except that if an old row in the table',
455
                    'has the same value as a new row for a PRIMARY KEY or a UNIQUE index,',
456
                    'the old row is deleted before the new row is inserted',
457
                ]),
458
            ],
459
            'REVOKE'    => [
460
                'Type'        => 'DCL',
461
                'description' => 'withdraw users access privileges given by using the GRANT command',
462
            ],
463
            'ROLLBACK'  => [
464
                'Type'        => 'DTL',
465
                'Description' => 'restore database to original since the last COMMIT',
466
            ],
467
            'SELECT'    => [
468
                'Type'        => 'DQL',
469
                'Description' => 'retrieve data from the a database',
470
            ],
471
            'SAVEPOINT' => [
472
                'Type'        => 'DTL',
473
                'Description' => 'identify a point in a transaction to which you can later roll back',
474
            ],
475
            'SET'       => [
476
                'Type'        => 'DTL',
477
                'Description' => 'change values of global/session variables or transaction characteristics',
478
            ],
479
            'SHOW'      => [
480
                'Type'        => 'DQL',
481
                'Description' => implode(' ', [
482
                    'has many forms that provide information about databases, tables, columns,',
483
                    'or status information about the server',
484
                ]),
485
            ],
486
            'START'     => [
487
                'Type'        => 'DTL',
488
                'Description' => 'marks the starting point for a transaction',
489
            ],
490
            'TRUNCATE'  => [
491
                'Type'        => 'DDL',
492
                'Description' => implode(', ', [
493
                    'remove all records from a table',
494
                    'including all spaces allocated for the records are removed'
495
                ]),
496
            ],
497
            'UPDATE'    => [
498
                'Type'        => 'DML',
499
                'Description' => 'updates existing data within a table',
500
            ],
501
            'USE'       => [
502
                'Type'        => 'DML',
503
                'Description' => implode(' ', [
504
                    'The USE db_name statement tells MySQL to use the db_name database',
505
                    'as the default (current) database for subsequent statements.',
506
                ]),
507
            ],
508
        ];
509
    }
510
511
    /**
512
     * Transforms an array into usable filters
513
     *
514
     * @param array $entryArray
515
     * @param string $referenceTable
516
     * @return array
517
     */
518
    private function setArrayToFilterValues($entryArray, $referenceTable = '')
519
    {
520
        $filters = '';
521
        if ($referenceTable != '') {
522
            $referenceTable = '`' . $referenceTable . '`.';
523
        }
524
        foreach ($entryArray as $key => $value) {
525
            if (is_array($value)) {
526
                $filters2 = '';
527
                foreach ($value as $value2) {
528
                    if ($value2 != '') {
529
                        if ($filters2 != '') {
530
                            $filters2 .= ',';
531
                        }
532
                        $filters2 .= '"' . $value2 . '"';
533
                    }
534
                }
535
                if ($filters2 != '') {
536
                    if ($filters != '') {
537
                        $filters .= ' AND ';
538
                    }
539
                    $filters .= ' ' . $referenceTable . '`' . $key
540
                            . '` IN ("' . str_replace(',', '","', str_replace(["'", '"'], '', $filters2))
541
                            . '")';
542
                }
543
            } else {
544
                if (($filters != '') && (!in_array($value, ['', '%%']))) {
545
                    $filters .= ' AND ';
546
                }
547
                if (!in_array($value, ['', '%%'])) {
548
                    if ((substr($value, 0, 1) == '%') && (substr($value, -1) == '%')) {
549
                        $filters .= ' ' . $key . ' LIKE "' . $value . '"';
550
                    } else {
551
                        $filters .= ' ' . $key . ' = "' . $value . '"';
552
                    }
553
                }
554
            }
555
        }
556
        return $filters;
557
    }
558
559
    private function stFldLmts($colType, $loLmt, $upLmt, $szN, $szUS)
560
    {
561
        $aReturn = ['m' => $loLmt, 'M' => $upLmt, 'l' => $szN];
562
        if (strpos($colType, 'unsigned') !== false) {
563
            $aReturn = ['m' => 0, 'M' => ($upLmt - $loLmt), 'l' => $szUS];
564
        }
565
        return $aReturn;
566
    }
567
568
    private function stFldLmtsExact($cTp)
569
    {
570
        $xct     = [
571
            'bigint'    => ['l' => -9223372036854775808, 'L' => 9223372036854775807, 's' => 21, 'sUS' => 20],
572
            'int'       => ['l' => -2147483648, 'L' => 2147483647, 's' => 11, 'sUS' => 10],
573
            'mediumint' => ['l' => -8388608, 'L' => 8388607, 's' => 9, 'sUS' => 8],
574
            'smallint'  => ['l' => -32768, 'L' => 32767, 's' => 6, 'sUS' => 5],
575
            'tinyint'   => ['l' => -128, 'L' => 127, 's' => 4, 'sUS' => 3],
576
        ];
577
        $sReturn = null;
578
        if (array_key_exists($cTp, $xct)) {
579
            $sReturn = $this->stFldLmts($cTp, $xct[$cTp]['l'], $xct[$cTp]['L'], $xct[$cTp]['s'], $xct[$cTp]['sUS']);
580
        }
581
        return $sReturn;
582
    }
583
584
    /**
585
     * Returns maximum length for a given MySQL field
586
     *
587
     * @param string $field_full_type
0 ignored issues
show
Bug introduced by
There is no parameter named $field_full_type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
588
     * @return array
589
     */
590
    protected function setFieldNumbers($fieldDetails, $outputFormated = false)
591
    {
592
        $sRtrn = $this->setFieldSpecific($fieldDetails);
593
        if ($outputFormated) {
594
            if (is_array($sRtrn)) {
595
                foreach ($sRtrn as $key => $value) {
596
                    $sRtrn[$key] = $this->setNumberFormat($value);
597
                }
598
            }
599
        }
600
        return $sRtrn;
601
    }
602
603
    private function setFieldSpecific($fieldDetails)
604
    {
605
        $sRtrn = '';
606
        if (in_array($fieldDetails['DATA_TYPE'], ['char', 'varchar', 'tinytext'])) {
607
            $sRtrn = ['M' => $fieldDetails['CHARACTER_MAXIMUM_LENGTH']];
608
        } elseif (in_array($fieldDetails['DATA_TYPE'], ['date'])) {
609
            $sRtrn = ['M' => 10];
610
        } elseif (in_array($fieldDetails['DATA_TYPE'], ['time'])) {
611
            $sRtrn = ['M' => 8];
612
        } elseif (in_array($fieldDetails['DATA_TYPE'], ['datetime', 'timestamp'])) {
613
            $sRtrn = ['M' => 19];
614
        } elseif (in_array($fieldDetails['DATA_TYPE'], ['decimal', 'numeric'])) {
615
            $sRtrn = ['M' => $fieldDetails['NUMERIC_PRECISION'], 'd' => $fieldDetails['NUMERIC_SCALE']];
616
        } elseif (in_array($fieldDetails['DATA_TYPE'], ['bigint', 'int', 'mediumint', 'smallint', 'tinyint'])) {
617
            $sRtrn = $this->stFldLmtsExact($fieldDetails['DATA_TYPE']);
618
        }
619
        return $sRtrn;
620
    }
621
622
    /**
623
     * Transmit Query to MySQL server and get results back
624
     *
625
     * @param string $sQuery
626
     * @param string $sReturnType
627
     * @param array $ftrs
628
     * @return boolean|array|string
629
     */
630
    protected function setMySQLquery2Server($sQuery, $sReturnType = null, $ftrs = null)
631
    {
632
        $aReturn = [
633
            'customError' => '',
634
            'result'      => null
635
        ];
636
        if (is_null($sReturnType)) {
637
            return $this->mySQLconnection->query(html_entity_decode($sQuery));
638
        } elseif (is_null($this->mySQLconnection)) {
639
            $aReturn['customError'] = $this->lclMsgCmn('i18n_MySQL_ConnectionNotExisting');
640
        } else {
641
            $result = $this->mySQLconnection->query(html_entity_decode($sQuery));
642
            if ($result) {
643
                switch (strtolower($sReturnType)) {
644
                    case 'array_first_key_rest_values':
645
                    case 'array_key_value':
646
                    case 'array_key_value2':
647
                    case 'array_key2_value':
648
                    case 'array_numbered':
649
                    case 'array_pairs_key_value':
650 View Code Duplication
                    case 'full_array_key_numbered':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
651
                        $aReturn           = $this->setMySQLquery2ServerByPattern([
652
                            'NoOfColumns' => $result->field_count,
653
                            'NoOfRows'    => $result->num_rows,
654
                            'QueryResult' => $result,
655
                            'returnType'  => $sReturnType,
656
                            'return'      => $aReturn
657
                        ]);
658
                        break;
659
                    case 'full_array_key_numbered_with_record_number_prefix':
660 View Code Duplication
                    case 'full_array_key_numbered_with_prefix':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
661
                        $aReturn           = $this->setMySQLquery2ServerByPattern([
662
                            'NoOfColumns' => $result->field_count,
663
                            'NoOfRows'    => $result->num_rows,
664
                            'QueryResult' => $result,
665
                            'returnType'  => $sReturnType,
666
                            'prefix'      => $ftrs['prefix'],
667
                            'return'      => $aReturn
668
                        ]);
669
                        break;
670
                    case 'id':
671
                        $aReturn['result'] = $this->mySQLconnection->insert_id;
672
                        break;
673
                    case 'lines':
674
                        $aReturn['result'] = $result->num_rows;
675
                        break;
676
                    case 'value':
677
                        if (($result->num_rows == 1) && ($result->field_count == 1)) {
678
                            $aReturn['result'] = $result->fetch_row()[0];
679
                        } else {
680
                            $msg                    = $this->lclMsgCmn('i18n_MySQL_QueryResultExpected1ResultedOther');
681
                            $aReturn['customError'] = sprintf($msg, $result->num_rows);
682
                        }
683
                        break;
684
                    default:
685
                        $msg                    = $this->lclMsgCmn('i18n_MySQL_QueryInvalidReturnTypeSpecified');
686
                        $aReturn['customError'] = sprintf($msg, $sReturnType, __FUNCTION__);
687
                        break;
688
                }
689
                if (is_object($result)) {
690
                    $result->close();
691
                }
692
            } else {
693
                $erNo                   = $this->mySQLconnection->errno;
694
                $erMsg                  = $this->mySQLconnection->error;
695
                $aReturn['customError'] = sprintf($this->lclMsgCmn('i18n_MySQL_QueryError'), $erNo, $erMsg);
696
            }
697
        }
698
        return $aReturn;
699
    }
700
701
    /**
702
     * Turns a raw query result into various structures
703
     * based on different predefined $parameters['returnType'] value
704
     *
705
     * @param array $parameters
706
     * @return array as ['customError' => '...', 'result' => '...']
707
     */
708
    protected function setMySQLquery2ServerByPattern($parameters)
709
    {
710
        $aReturn    = $parameters['return'];
711
        $buildArray = false;
712
        switch ($parameters['returnType']) {
713 View Code Duplication
            case 'array_first_key_rest_values':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
714
                if ($parameters['NoOfColumns'] >= 2) {
715
                    $buildArray = true;
716
                } else {
717
                    $msg                    = $this->lclMsgCmn('QueryResultExpectedAtLeast2ColsResultedOther');
718
                    $aReturn['customError'] = sprintf($msg, $parameters['NoOfColumns']);
719
                }
720
                break;
721
            case 'array_key_value':
722
            case 'array_key_value2':
723 View Code Duplication
            case 'array_key2_value':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
724
                if ($parameters['NoOfColumns'] == 2) {
725
                    $buildArray = true;
726
                } else {
727
                    $msg                    = $this->lclMsgCmn('i18n_MySQL_QueryResultExpected2ColumnsResultedOther');
728
                    $aReturn['customError'] = sprintf($msg, $parameters['NoOfColumns']);
729
                }
730
                break;
731 View Code Duplication
            case 'array_numbered':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
732
                if ($parameters['NoOfColumns'] == 1) {
733
                    $buildArray = true;
734
                } else {
735
                    $msg                    = $this->lclMsgCmn('i18n_MySQL_QueryResultExpected1ColumnResultedOther');
736
                    $aReturn['customError'] = sprintf($msg, $parameters['NoOfColumns']);
737
                }
738
                break;
739
            case 'array_pairs_key_value':
740
                if (($parameters['NoOfRows'] == 1) && ($parameters['NoOfColumns'] > 1)) {
741
                    $buildArray = true;
742
                } else {
743
                    $shorterLclString       = 'i18n_MySQL_QueryResultExpected1RowManyColumnsResultedOther';
744
                    $msg                    = $this->lclMsgCmn($shorterLclString);
745
                    $aReturn['customError'] = sprintf($msg, $parameters['NoOfRows'], $parameters['NoOfColumns']);
746
                }
747
                break;
748
            case 'full_array_key_numbered':
749
            case 'full_array_key_numbered_with_prefix':
750
            case 'full_array_key_numbered_with_record_number_prefix':
751
                if ($parameters['NoOfColumns'] == 0) {
752
                    $aReturn['customError'] = $this->lclMsgCmn('i18n_MySQL_QueryResultExpected1OrMoreRows0Resulted');
753
                    if (in_array($parameters['returnType'], [
754
                                'full_array_key_numbered_with_prefix',
755
                                'full_array_key_numbered_with_record_number_prefix',
756
                            ])) {
757
                        $aReturn['result'][$parameters['prefix']] = null;
758
                    }
759
                } else {
760
                    $buildArray = true;
761
                }
762
                break;
763
            default:
764
                $aReturn['customError'] = $parameters['returnType'] . ' is not defined!';
765
                break;
766
        }
767
        if ($buildArray) {
768
            $counter2 = 0;
769
            for ($counter = 0; $counter < $parameters['NoOfRows']; $counter++) {
770
                $line = $parameters['QueryResult']->fetch_row();
771
                switch ($parameters['returnType']) {
772
                    case 'array_first_key_rest_values':
773
                        $finfo         = $parameters['QueryResult']->fetch_fields();
774
                        $columnCounter = 0;
775
                        foreach ($finfo as $value) {
776
                            if ($columnCounter != 0) {
777
                                $aReturn['result'][$line[0]][$value->name] = $line[$columnCounter];
778
                            }
779
                            $columnCounter++;
780
                        }
781
                        break;
782
                    case 'array_key_value':
783
                        $aReturn['result'][$line[0]]                  = $line[1];
784
                        break;
785
                    case 'array_key_value2':
786
                        $aReturn['result'][$line[0]][]                = $line[1];
787
                        break;
788
                    case 'array_key2_value':
789
                        $aReturn['result'][$line[0] . '@' . $line[1]] = $line[1];
790
                        break;
791
                    case 'array_numbered':
792
                        $aReturn['result'][]                          = $line[0];
793
                        break;
794
                    case 'array_pairs_key_value':
795
                        $finfo                                        = $parameters['QueryResult']->fetch_fields();
796
                        $columnCounter                                = 0;
797
                        foreach ($finfo as $value) {
798
                            $aReturn['result'][$value->name] = $line[$columnCounter];
799
                            $columnCounter++;
800
                        }
801
                        break;
802
                    case 'full_array_key_numbered':
803
                        $finfo         = $parameters['QueryResult']->fetch_fields();
804
                        $columnCounter = 0;
805
                        foreach ($finfo as $value) {
806
                            $aReturn['result'][$counter2][$value->name] = $line[$columnCounter];
807
                            $columnCounter++;
808
                        }
809
                        $counter2++;
810
                        break;
811
                    case 'full_array_key_numbered_with_record_number_prefix':
812
                        $parameters['prefix'] = 'RecordNo';
813
                    // intentionally left open
814
                    case 'full_array_key_numbered_with_prefix':
815
                        $finfo                = $parameters['QueryResult']->fetch_fields();
816
                        $columnCounter        = 0;
817
                        foreach ($finfo as $value) {
818
                            $aReturn['result'][$parameters['prefix']][$counter2][$value->name] = $line[$columnCounter];
819
                            $columnCounter++;
820
                        }
821
                        $counter2++;
822
                        break;
823
                }
824
            }
825
        }
826
        return $aReturn;
827
    }
828
}
829