Passed
Push — main ( af1024...b746de )
by Thierry
02:04
created

Driver   F

Complexity

Total Complexity 66

Size/Duplication

Total Lines 548
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 129
dl 0
loc 548
rs 3.12
c 4
b 0
f 0
wmc 66

41 Methods

Rating   Name   Duplication   Size   Complexity  
A options() 0 22 5
A rows() 0 14 4
A charset() 0 4 2
A minVersion() 0 11 4
A type() 0 3 1
A types() 0 3 1
A editFunctions() 0 3 1
A __construct() 0 9 1
A operators() 0 3 1
A structuredTypes() 0 3 1
A setUtf8mb4() 0 9 3
A inout() 0 4 1
A rollback() 0 4 1
A schema() 0 3 1
A error() 0 3 1
A begin() 0 4 1
A setError() 0 3 1
A errno() 0 3 1
A database() 0 3 1
A enumLength() 0 4 1
A config() 0 3 1
A hasError() 0 3 1
A typeExists() 0 3 1
A commit() 0 4 1
A hasErrno() 0 3 1
A keyValues() 0 17 5
A setErrno() 0 3 1
A setStructuredType() 0 3 1
A actions() 0 3 1
A onActions() 0 3 1
A applyQueries() 0 13 4
A queries() 0 3 1
A grouping() 0 3 1
A numberRegex() 0 3 1
A jush() 0 3 1
A unsigned() 0 3 1
A execute() 0 7 3
A connect() 0 7 2
A functions() 0 3 1
A values() 0 10 3
A version() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Driver 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.

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 Driver, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Lagdo\DbAdmin\Driver;
4
5
use Lagdo\DbAdmin\Driver\Entity\ConfigEntity;
6
7
use Lagdo\DbAdmin\Driver\Db\ConnectionInterface;
8
use Lagdo\DbAdmin\Driver\Db\ServerInterface;
9
use Lagdo\DbAdmin\Driver\Db\DatabaseInterface;
10
use Lagdo\DbAdmin\Driver\Db\TableInterface;
11
use Lagdo\DbAdmin\Driver\Db\QueryInterface;
12
use Lagdo\DbAdmin\Driver\Db\GrammarInterface;
13
14
use Lagdo\DbAdmin\Driver\Exception\AuthException;
15
16
abstract class Driver implements DriverInterface
17
{
18
    use ServerTrait;
19
    use TableTrait;
20
    use DatabaseTrait;
21
    use QueryTrait;
22
    use GrammarTrait;
23
    use ConnectionTrait;
24
25
    /**
26
     * @var UtilInterface
27
     */
28
    protected $util;
29
30
    /**
31
     * @var TranslatorInterface
32
     */
33
    protected $trans;
34
35
    /**
36
     * @var ServerInterface
37
     */
38
    protected $server;
39
40
    /**
41
     * @var DatabaseInterface
42
     */
43
    protected $database;
44
45
    /**
46
     * @var TableInterface
47
     */
48
    protected $table;
49
50
    /**
51
     * @var QueryInterface
52
     */
53
    protected $query;
54
55
    /**
56
     * @var GrammarInterface
57
     */
58
    protected $grammar;
59
60
    /**
61
     * @var ConnectionInterface
62
     */
63
    protected $connection;
64
65
    /**
66
     * @var ConfigEntity
67
     */
68
    protected $config;
69
70
    /**
71
     * @var array
72
     */
73
    protected $options;
74
75
    /**
76
     * From bootstrap.inc.php
77
     * @var string
78
     */
79
    public $onActions = 'RESTRICT|NO ACTION|CASCADE|SET NULL|SET DEFAULT'; ///< @var string used in foreignKeys()
80
81
    /**
82
     * The current database name
83
     *
84
     * @var string
85
     */
86
    protected $databaseName = '';
87
88
    /**
89
     * The current schema name
90
     *
91
     * @var string
92
     */
93
    protected $schemaName = '';
94
95
    /**
96
     * Executed queries
97
     *
98
     * @var array
99
     */
100
    protected $queries = [];
101
102
    /**
103
     * Query start timestamp
104
     *
105
     * @var int
106
     */
107
    protected $start = 0;
108
109
    /**
110
     * The last error code
111
     *
112
     * @var int
113
     */
114
    protected $errno = 0;
115
116
    /**
117
     * The last error message
118
     *
119
     * @var string
120
     */
121
    protected $error = '';
122
123
    /**
124
     * The constructor
125
     *
126
     * @param UtilInterface $util
127
     * @param TranslatorInterface $trans
128
     * @param array $options
129
     */
130
    public function __construct(UtilInterface $util, TranslatorInterface $trans, array $options)
131
    {
132
        $this->util = $util;
133
        $this->util->setDriver($this);
134
        $this->trans = $trans;
135
        $this->options = $options;
136
        $this->config = new ConfigEntity();
137
        $this->initConfig();
138
        $this->createConnection();
139
    }
140
141
    /**
142
     * Set driver config
143
     *
144
     * @return void
145
     */
146
    abstract protected function initConfig();
147
148
    /**
149
     * @inheritDoc
150
     */
151
    public function version()
152
    {
153
        return '4.8.1-dev';
154
    }
155
156
    /**
157
     * @inheritDoc
158
     */
159
    public function options(string $name = '')
160
    {
161
        if (!($name = trim($name))) {
162
            return $this->options;
163
        }
164
        if (\array_key_exists($name, $this->options)) {
165
            return $this->options[$name];
166
        }
167
        if ($name === 'server') {
168
            $server = $this->options['host'] ?? '';
169
            $port = $this->options['port'] ?? ''; // Optional
170
            // Append the port to the host if it is defined.
171
            if (($port)) {
172
                $server .= ":$port";
173
            }
174
            return $server;
175
        }
176
        // if ($name === 'ssl') {
177
        //     return false; // No SSL options yet
178
        // }
179
        // Option not found
180
        return '';
181
    }
182
183
    /**
184
     * @inheritDoc
185
     */
186
    public function connect(string $database, string $schema)
187
    {
188
        if (!$this->connection->open($database, $schema)) {
189
            throw new AuthException($this->error());
190
        }
191
        $this->databaseName = $database;
192
        $this->schemaName = $schema;
193
    }
194
195
    /**
196
     * @inheritDoc
197
     */
198
    public function numberRegex()
199
    {
200
        return '((?<!o)int(?!er)|numeric|real|float|double|decimal|money)'; // not point, not interval
201
    }
202
203
    /**
204
     * @inheritDoc
205
     */
206
    public function database()
207
    {
208
        return $this->databaseName;
209
    }
210
211
    /**
212
     * @inheritDoc
213
     */
214
    public function schema()
215
    {
216
        return $this->schemaName;
217
    }
218
219
    /**
220
     * @inheritDoc
221
     */
222
    public function config()
223
    {
224
        return $this->config;
225
    }
226
227
    /**
228
     * @inheritDoc
229
     */
230
    public function minVersion(string $version, string $mariaDb = '', ConnectionInterface $connection = null)
231
    {
232
        if (!$connection) {
233
            $connection = $this->connection;
234
        }
235
        $info = $connection->serverInfo();
236
        if ($mariaDb && preg_match('~([\d.]+)-MariaDB~', $info, $match)) {
237
            $info = $match[1];
238
            $version = $mariaDb;
239
        }
240
        return (version_compare($info, $version) >= 0);
241
    }
242
243
    /**
244
     * @inheritDoc
245
     */
246
    public function charset()
247
    {
248
        // SHOW CHARSET would require an extra query
249
        return ($this->minVersion('5.5.3', 0) ? 'utf8mb4' : 'utf8');
250
    }
251
252
    /**
253
     * @inheritDoc
254
     */
255
    public function begin()
256
    {
257
        $result = $this->connection->query("BEGIN");
258
        return $result !== false;
259
    }
260
261
    /**
262
     * @inheritDoc
263
     */
264
    public function commit()
265
    {
266
        $result = $this->connection->query("COMMIT");
267
        return $result !== false;
268
    }
269
270
    /**
271
     * @inheritDoc
272
     */
273
    public function rollback()
274
    {
275
        $result = $this->connection->query("ROLLBACK");
276
        return $result !== false;
277
    }
278
279
    /**
280
     * @inheritDoc
281
     */
282
    public function setUtf8mb4(string $create)
283
    {
284
        static $set = false;
285
        // possible false positive
286
        if (!$set && preg_match('~\butf8mb4~i', $create)) {
287
            $set = true;
288
            return 'SET NAMES ' . $this->charset() . ";\n\n";
289
        }
290
        return '';
291
    }
292
293
    /**
294
     * @return string
295
     */
296
    public function inout()
297
    {
298
        // From index.php
299
        return 'IN|OUT|INOUT';
300
    }
301
302
    /**
303
     * @return string
304
     */
305
    public function enumLength()
306
    {
307
        // From index.php
308
        return "'(?:''|[^'\\\\]|\\\\.)*'";
309
    }
310
311
    /**
312
     * @return string
313
     */
314
    public function actions()
315
    {
316
        return $this->onActions;
317
    }
318
319
    /**
320
     * @return array
321
     */
322
    public function onActions()
323
    {
324
        return \explode('|', $this->onActions);
325
    }
326
327
    /**
328
     * Get the server jush
329
     *
330
     * @return string
331
     */
332
    public function jush()
333
    {
334
        return $this->config->jush;
335
    }
336
337
    /**
338
     * @return array
339
     */
340
    public function unsigned()
341
    {
342
        return $this->config->unsigned;
343
    }
344
345
    /**
346
     * @return array
347
     */
348
    public function functions()
349
    {
350
        return $this->config->functions;
351
    }
352
353
    /**
354
     * @return array
355
     */
356
    public function grouping()
357
    {
358
        return $this->config->grouping;
359
    }
360
361
    /**
362
     * @return array
363
     */
364
    public function operators()
365
    {
366
        return $this->config->operators;
367
    }
368
369
    /**
370
     * @return array
371
     */
372
    public function editFunctions()
373
    {
374
        return $this->config->editFunctions;
375
    }
376
377
    /**
378
     * @return array
379
     */
380
    public function types()
381
    {
382
        return $this->config->types;
383
    }
384
385
    /**
386
     * @param string $type
387
     *
388
     * @return bool
389
     */
390
    public function typeExists(string $type)
391
    {
392
        return isset($this->config->types[$type]);
393
    }
394
395
    /**
396
     * @param string $type
397
     *
398
     * @return mixed
399
     */
400
    public function type(string $type)
401
    {
402
        return $this->config->types[$type];
403
    }
404
405
    /**
406
     * @return array
407
     */
408
    public function structuredTypes()
409
    {
410
        return $this->config->structuredTypes;
411
    }
412
413
    /**
414
     * @param string $key
415
     * @param mixed $value
416
     *
417
     * @return void
418
     */
419
    public function setStructuredType(string $key, $value)
420
    {
421
        $this->config->structuredTypes[$key] = $value;
422
    }
423
424
    /**
425
     * @inheritDoc
426
     */
427
    public function setError(string $error = '')
428
    {
429
        $this->error = $error;
430
    }
431
432
    /**
433
     * @inheritDoc
434
     */
435
    public function error()
436
    {
437
        return $this->error;
438
    }
439
440
    /**
441
     * @inheritDoc
442
     */
443
    public function hasError()
444
    {
445
        return $this->error !== '';
446
    }
447
448
    /**
449
     * @inheritDoc
450
     */
451
    public function setErrno($errno)
452
    {
453
        $this->errno = $errno;
454
    }
455
456
    /**
457
     * @inheritDoc
458
     */
459
    public function errno()
460
    {
461
        return $this->errno;
462
    }
463
464
    /**
465
     * @inheritDoc
466
     */
467
    public function hasErrno()
468
    {
469
        return $this->errno !== 0;
470
    }
471
472
    /**
473
     * @inheritDoc
474
     */
475
    public function execute(string $query)
476
    {
477
        if (!$this->start) {
478
            $this->start = intval(microtime(true));
479
        }
480
        $this->queries[] = (preg_match('~;$~', $query) ? "DELIMITER ;;\n$query;\nDELIMITER " : $query) . ";";
481
        return $this->connection->query($query);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->connection->query($query) also could return the type Lagdo\DbAdmin\Driver\Db\StatementInterface which is incompatible with the return type mandated by Lagdo\DbAdmin\Driver\DriverInterface::execute() of Lagdo\DbAdmin\Driver\StatementInterface|boolean.
Loading history...
482
    }
483
484
    /**
485
     * @inheritDoc
486
     */
487
    public function queries()
488
    {
489
        return [implode("\n", $this->queries), $this->trans->formatTime($this->start)];
490
    }
491
492
    /**
493
     * @inheritDoc
494
     */
495
    public function applyQueries(string $query, array $tables, $escape = null)
496
    {
497
        if (!$escape) {
498
            $escape = function ($table) {
499
                return $this->driver->table($table);
0 ignored issues
show
Bug Best Practice introduced by
The property driver does not exist on Lagdo\DbAdmin\Driver\Driver. Did you maybe forget to declare it?
Loading history...
500
            };
501
        }
502
        foreach ($tables as $table) {
503
            if (!$this->execute("$query " . $escape($table))) {
504
                return false;
505
            }
506
        }
507
        return true;
508
    }
509
510
    /**
511
     * @inheritDoc
512
     */
513
    public function values(string $query, $column = 0)
514
    {
515
        $values = [];
516
        $statement = $this->connection->query($query);
517
        if (is_object($statement)) {
518
            while ($row = $statement->fetchRow()) {
519
                $values[] = $row[$column];
520
            }
521
        }
522
        return $values;
523
    }
524
525
    /**
526
     * @inheritDoc
527
     */
528
    public function keyValues(string $query, ConnectionInterface $connection = null, bool $setKeys = true)
529
    {
530
        if (!is_object($connection)) {
531
            $connection = $this->connection;
532
        }
533
        $values = [];
534
        $statement = $connection->query($query);
535
        if (is_object($statement)) {
536
            while ($row = $statement->fetchRow()) {
537
                if ($setKeys) {
538
                    $values[$row[0]] = $row[1];
539
                } else {
540
                    $values[] = $row[0];
541
                }
542
            }
543
        }
544
        return $values;
545
    }
546
547
    /**
548
     * @inheritDoc
549
     */
550
    public function rows(string $query, ConnectionInterface $connection = null)
551
    {
552
        if (!$connection) {
553
            $connection = $this->connection;
554
        }
555
        $statement = $connection->query($query);
556
        if (!is_object($statement)) { // can return true
557
            return [];
558
        }
559
        $rows = [];
560
        while ($row = $statement->fetchAssoc()) {
561
            $rows[] = $row;
562
        }
563
        return $rows;
564
    }
565
}
566