Passed
Push — master ( e473b2...f755b5 )
by Sébastien
02:42 queued 13s
created

SimpleConnection   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 411
Duplicated Lines 0 %

Test Coverage

Coverage 94.35%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 43
eloc 105
c 2
b 0
f 0
dl 0
loc 411
ccs 117
cts 124
cp 0.9435
rs 8.96

29 Methods

Rating   Name   Duplication   Size   Complexity  
A beginTransaction() 0 5 1
A make() 0 3 1
A runOrReconnect() 0 20 4
A execute() 0 19 4
A exec() 0 6 1
A getName() 0 3 1
A commit() 0 5 1
A prepare() 0 4 1
A prepareLogger() 0 6 3
A from() 0 3 1
A executeQuery() 0 6 1
A __construct() 0 14 1
A schema() 0 7 2
A setName() 0 5 1
A factory() 0 3 1
A close() 0 5 1
A isConnected() 0 3 1
A executePrepared() 0 26 4
A toDatabase() 0 3 1
A select() 0 10 1
A rollBack() 0 5 1
A delete() 0 3 1
A query() 0 8 1
A insert() 0 3 1
A platform() 0 11 3
A executeUpdate() 0 6 1
A builder() 0 3 1
A fromDatabase() 0 3 1
A update() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like SimpleConnection 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 SimpleConnection, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Bdf\Prime\Connection;
4
5
use Bdf\Prime\Connection\Event\ConnectionClosedListenerInterface;
6
use Bdf\Prime\Connection\Extensions\LostConnection;
7
use Bdf\Prime\Connection\Extensions\SchemaChanged;
8
use Bdf\Prime\Connection\Result\PdoResultSet;
9
use Bdf\Prime\Connection\Result\ResultSetInterface;
10
use Bdf\Prime\Connection\Result\UpdateResultSet;
11
use Bdf\Prime\Exception\DBALException;
12
use Bdf\Prime\Exception\PrimeException;
13
use Bdf\Prime\Platform\Sql\SqlPlatform;
14
use Bdf\Prime\Query\Compiler\Preprocessor\PreprocessorInterface;
15
use Bdf\Prime\Query\Compiler\SqlCompiler;
16
use Bdf\Prime\Query\Contract\Compilable;
17
use Bdf\Prime\Query\Contract\Query\InsertQueryInterface;
18
use Bdf\Prime\Query\Contract\Query\KeyValueQueryInterface;
19
use Bdf\Prime\Query\Custom\BulkInsert\BulkInsertQuery;
20
use Bdf\Prime\Query\Custom\BulkInsert\BulkInsertSqlCompiler;
21
use Bdf\Prime\Query\Custom\KeyValue\KeyValueQuery;
22
use Bdf\Prime\Query\Custom\KeyValue\KeyValueSqlCompiler;
23
use Bdf\Prime\Query\Factory\DefaultQueryFactory;
24
use Bdf\Prime\Query\Factory\QueryFactoryInterface;
25
use Bdf\Prime\Query\Query;
26
use Bdf\Prime\Schema\SchemaManager;
27
use Closure;
28
use Doctrine\Common\EventManager;
29
use Doctrine\DBAL\Cache\QueryCacheProfile;
30
use Doctrine\DBAL\Configuration;
31
use Doctrine\DBAL\Connection as BaseConnection;
32
use Doctrine\DBAL\DBALException as DoctrineDBALException;
33
use Doctrine\DBAL\Driver;
34
use Doctrine\DBAL\Statement;
35
use PDO;
36
37
/**
38
 * Connection
39
 *
40
 * @package Bdf\Prime
0 ignored issues
show
Coding Style Documentation introduced by
@package tag is not allowed in class comment
Loading history...
41
 */
42
class SimpleConnection extends BaseConnection implements ConnectionInterface
43
{
44
    use LostConnection;
45
    use SchemaChanged;
46
47
    /**
48
     * The connection name.
49
     *
50
     * @var string
51
     */
52
    protected $name;
53
    
54
    /**
55
     * The schema manager.
56
     *
57
     * @var SchemaManager
58
     */
59
    private $schema;
60
61
    /**
62
     * @var SqlPlatform
63
     */
64
    private $platform;
65
66
    /**
67
     * @var QueryFactoryInterface
68
     */
69
    private $factory;
70
71
    /**
72
     * SimpleConnection constructor.
73
     *
74
     * @param array $params
75
     * @param Driver $driver
76
     * @param Configuration|null $config
77
     * @param EventManager|null $eventManager
78
     * @throws DoctrineDBALException
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
introduced by
Comment missing for @throws tag in function comment
Loading history...
79
     */
80 149
    public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null)
81
    {
82 149
        parent::__construct($params, $driver, $config, $eventManager);
83
84 149
        $this->factory = new DefaultQueryFactory(
85 149
            $this,
86 149
            new SqlCompiler($this),
87
            [
88 149
                KeyValueQuery::class   => KeyValueSqlCompiler::class,
89
                BulkInsertQuery::class => BulkInsertSqlCompiler::class,
90
            ],
91
            [
92 149
                KeyValueQueryInterface::class => KeyValueQuery::class,
93
                InsertQueryInterface::class   => BulkInsertQuery::class,
94
            ]
95
        );
96 149
    }
97
98
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $name should have a doc-comment as per coding-style.
Loading history...
99
     * {@inheritdoc}
100
     */
101 150
    public function setName($name)
102
    {
103 150
        $this->name = $name;
104
        
105 150
        return $this;
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111 159
    public function getName()
112
    {
113 159
        return $this->name;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 1
    public function isConnected()
120
    {
121 1
        return $this->_conn !== null;
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127 802
    public function schema()
128
    {
129 802
        if ($this->schema === null) {
130 132
            $this->schema = new SchemaManager($this);
131
        }
132
133 802
        return $this->schema;
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
139 1025
    public function platform()
140
    {
141 1025
        if ($this->platform === null) {
142
            try {
143 138
                $this->platform = new SqlPlatform($this->getDatabasePlatform(), $this->getConfiguration()->getTypes());
0 ignored issues
show
introduced by
The method getTypes() does not exist on Doctrine\DBAL\Configuration. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

143
                $this->platform = new SqlPlatform($this->getDatabasePlatform(), $this->getConfiguration()->/** @scrutinizer ignore-call */ getTypes());
Loading history...
144
            } catch (DoctrineDBALException $e) {
145
                throw new DBALException($e->getMessage(), $e->getCode(), $e);
146
            }
147
        }
148
149 1025
        return $this->platform;
150
    }
151
152
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $value should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $type should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $fieldOptions should have a doc-comment as per coding-style.
Loading history...
153
     * {@inheritdoc}
154
     */
155 3
    public function fromDatabase($value, $type, array $fieldOptions = [])
156
    {
157 3
        return $this->platform()->types()->fromDatabase($value, $type, $fieldOptions);
0 ignored issues
show
Bug introduced by
The method fromDatabase() does not exist on Bdf\Prime\Types\TypesRegistryInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Bdf\Prime\Types\TypesRegistry. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

157
        return $this->platform()->types()->/** @scrutinizer ignore-call */ fromDatabase($value, $type, $fieldOptions);
Loading history...
158
    }
159
160
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $value should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $type should have a doc-comment as per coding-style.
Loading history...
161
     * {@inheritdoc}
162
     */
163 4
    public function toDatabase($value, $type = null)
164
    {
165 4
        return $this->platform()->types()->toDatabase($value, $type);
0 ignored issues
show
Bug introduced by
The method toDatabase() does not exist on Bdf\Prime\Types\TypesRegistryInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Bdf\Prime\Types\TypesRegistry. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

165
        return $this->platform()->types()->/** @scrutinizer ignore-call */ toDatabase($value, $type);
Loading history...
166
    }
167
168
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $preprocessor should have a doc-comment as per coding-style.
Loading history...
169
     * {@inheritdoc}
170
     */
171 658
    public function builder(PreprocessorInterface $preprocessor = null)
172
    {
173 658
        return $this->factory->make(Query::class, $preprocessor);
174
    }
175
176
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $query should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $preprocessor should have a doc-comment as per coding-style.
Loading history...
177
     * {@inheritdoc}
178
     */
179 183
    public function make($query, PreprocessorInterface $preprocessor = null)
180
    {
181 183
        return $this->factory->make($query, $preprocessor);
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187 817
    public function factory()
188
    {
189 817
        return $this->factory;
190
    }
191
192
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $alias should have a doc-comment as per coding-style.
Loading history...
193
     * {@inheritdoc}
194
     */
195 503
    public function from($table, string $alias = null)
196
    {
197 503
        return $this->builder()->from($table, $alias);
198
    }
199
200
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $identifier should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $types should have a doc-comment as per coding-style.
Loading history...
201
     * {@inheritdoc}
202
     */
203 13
    public function delete($table, array $identifier, array $types = array())
0 ignored issues
show
Coding Style introduced by
The method parameter $types is never used
Loading history...
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
204
    {
205 13
        return $this->from($table)->where($identifier)->delete();
0 ignored issues
show
Bug introduced by
The method where() does not exist on Bdf\Prime\Query\CommandInterface. It seems like you code against a sub-type of Bdf\Prime\Query\CommandInterface such as Bdf\Prime\Query\Contract...\KeyValueQueryInterface or Bdf\Prime\Query\QueryInterface or Bdf\Prime\Query\AbstractReadCommand. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

205
        return $this->from($table)->/** @scrutinizer ignore-call */ where($identifier)->delete();
Loading history...
206
    }
207
    
208
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $identifier should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $types should have a doc-comment as per coding-style.
Loading history...
209
     * {@inheritdoc}
210
     */
211 1
    public function update($table, array $data, array $identifier, array $types = array())
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
212
    {
213 1
        return $this->from($table)->where($identifier)->update($data, $types);
214
    }
215
216
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $table should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $data should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $types should have a doc-comment as per coding-style.
Loading history...
217
     * {@inheritdoc}
218
     */
219 401
    public function insert($table, array $data, array $types = array())
0 ignored issues
show
Coding Style introduced by
Short array syntax must be used to define arrays
Loading history...
220
    {
221 401
        return $this->from($table)->insert($data, $types);
0 ignored issues
show
Bug introduced by
The method insert() does not exist on Bdf\Prime\Query\CommandInterface. It seems like you code against a sub-type of Bdf\Prime\Query\CommandInterface such as Bdf\Prime\Query\QueryInterface or Bdf\Prime\Query\AbstractReadCommand or Bdf\Prime\Sharding\Query\ShardingKeyValueQuery or Bdf\Prime\Query\Custom\KeyValue\KeyValueQuery. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

221
        return $this->from($table)->/** @scrutinizer ignore-call */ insert($data, $types);
Loading history...
222
    }
223
224
    /**
225
     * Executes select query and returns array of object
226
     * 
227
     * @param string $query
228
     * @param array  $bindings
229
     * @param array  $types
230
     * 
231
     * @return array
232
     */
233 2
    public function select($query, array $bindings = [], array $types = [])
234
    {
235 2
        $stmt = $this->executeQuery($query, $bindings, $types);
236 2
        $stmt->setFetchMode(PDO::FETCH_OBJ);
237
238 2
        $result = $stmt->fetchAll();
239
240 2
        $stmt->closeCursor();
241
        
242 2
        return $result;
243
    }
244
245
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $query should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $params should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $types should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $qcp should have a doc-comment as per coding-style.
Loading history...
246
     * {@inheritdoc}
247
     */
248 817
    public function executeQuery($query, array $params = [], $types = [], QueryCacheProfile $qcp = null)
249
    {
250 817
        $this->prepareLogger();
251
252
        return $this->runOrReconnect(function() use ($query, $params, $types, $qcp) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
253 817
            return parent::executeQuery($query, $params, $types, $qcp);
254 817
        });
255
    }
256
257
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $query should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $params should have a doc-comment as per coding-style.
Loading history...
Coding Style introduced by
Parameter $types should have a doc-comment as per coding-style.
Loading history...
258
     * {@inheritdoc}
259
     */
260 458
    public function executeUpdate($query, array $params = [], array $types = [])
261
    {
262 458
        $this->prepareLogger();
263
264
        return $this->runOrReconnect(function() use ($query, $params, $types) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
265 458
            return parent::executeUpdate($query, $params, $types);
266 458
        });
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272 6
    public function query()
273
    {
274 6
        $this->prepareLogger();
275
        
276 6
        $args = func_get_args();
277
278
        return $this->runOrReconnect(function() use ($args) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
279 6
            return parent::query(...$args);
280 6
        });
281
    }
282
    
283
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $statement should have a doc-comment as per coding-style.
Loading history...
284
     * {@inheritdoc}
285
     *
286
     * @throws PrimeException
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
287
     */
288 801
    public function exec($statement)
289
    {
290 801
        $this->prepareLogger();
291
        
292
        return $this->runOrReconnect(function() use ($statement) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
293 801
            return parent::exec($statement);
294 801
        });
295
    }
296
297
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $statement should have a doc-comment as per coding-style.
Loading history...
298
     * {@inheritdoc}
299
     *
300
     * @throws PrimeException
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
301
     */
302 495
    public function prepare($statement)
303
    {
304
        return $this->runOrReconnect(function() use ($statement) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
305 495
            return parent::prepare($statement);
306 495
        });
307
    }
308
309
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $query should have a doc-comment as per coding-style.
Loading history...
310
     * {@inheritdoc}
311
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
312 613
    public function execute(Compilable $query)
313
    {
314
        try {
315 613
            $statement = $query->compile();
316
317 610
            if ($statement instanceof Statement) {
318 468
                return $this->executePrepared($statement, $query);
319
            }
320
321
            // $statement is a SQL query
322 557
            if ($query->type() === Compilable::TYPE_SELECT) {
323 502
                $stmt = $this->executeQuery($statement, $query->getBindings());
324
325 502
                return new PdoResultSet($stmt);
326
            }
327
328 455
            return new UpdateResultSet($this->executeUpdate($statement, $query->getBindings()));
329 12
        } catch (DoctrineDBALException $e) {
330 7
            throw new DBALException('Error on execute : '.$e->getMessage(), $e->getCode(), $e);
331
        }
332
    }
333
334
    /**
335
     * Execute a prepared statement
336
     *
337
     * @param Statement $statement
338
     * @param Compilable $query
339
     *
340
     * @return ResultSetInterface The query result
341
     * @throws DoctrineDBALException
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
342
     * @throws PrimeException
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
343
     */
0 ignored issues
show
Coding Style introduced by
Expected 1 @throws tag(s) in function comment; 2 found
Loading history...
344 468
    protected function executePrepared(Statement $statement, Compilable $query)
345
    {
346 468
        $bindings = $query->getBindings();
347
348 468
        $this->prepareLogger();
349
350
        try {
351 468
            $statement->execute($bindings);
352 329
        } catch (DoctrineDBALException $exception) {
353
            // Prepared query on SQLite for PHP < 7.2 invalidates the query when schema change
354
            // This process may be removed on PHP 7.2
355 329
            if ($this->causedBySchemaChange($exception)) {
356 324
                $statement = $query->compile(true);
357 324
                $statement->execute($query->getBindings());
358 6
            } elseif ($this->causedByLostConnection($exception->getPrevious())) { // If the connection is lost, the query must be recompiled
0 ignored issues
show
Coding Style introduced by
Usage of ELSEIF not allowed; use ELSE IF instead
Loading history...
introduced by
There should be no white space after an opening "{"
Loading history...
Coding Style introduced by
Comments may not appear after statements
Loading history...
359
                $this->close();
360
                $this->connect();
361
362
                $statement = $query->compile(true);
363
                $statement->execute($query->getBindings());
364
            } else {
365 6
                throw $exception;
366
            }
367
        }
368
369 466
        return new PdoResultSet($statement);
370
    }
371
372
    /**
373
     * {@inheritdoc}
374
     */
375 822
    public function beginTransaction()
376
    {
377 822
        $this->prepareLogger();
378
379 822
        parent::beginTransaction();
380 822
    }
381
382
    /**
383
     * {@inheritdoc}
384
     */
385 28
    public function commit()
386
    {
387 28
        $this->prepareLogger();
388
        
389 28
        parent::commit();
390 28
    }
391
    
392
    /**
393
     * {@inheritdoc}
394
     */
395 797
    public function rollBack()
396
    {
397 797
        $this->prepareLogger();
398
        
399 797
        return parent::rollBack();
0 ignored issues
show
Bug introduced by
Are you sure the usage of parent::rollBack() targeting Doctrine\DBAL\Connection::rollBack() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
400
    }
401
402
    /**
403
     * {@inheritdoc}
404
     */
405 16
    public function close()
406
    {
407 16
        parent::close();
408
409 16
        $this->_eventManager->dispatchEvent(ConnectionClosedListenerInterface::EVENT_NAME);
410 16
    }
411
412
    /**
413
     * Setup the logger by setting the connection
414
     */
415 957
    protected function prepareLogger()
416
    {
417 957
        $logger = $this->getConfiguration()->getSQLLogger();
418
419 957
        if ($logger && $logger instanceof ConnectionAwareInterface) {
420
            $logger->setConnection($this);
421
        }
422 957
    }
423
424
    /**
425
     * Execute a query. Try to reconnect if needed
426
     *
427
     * @param Closure $callback
428
     *
429
     * @return mixed  The query result
430
     *
431
     * @throws DBALException
0 ignored issues
show
introduced by
Comment missing for @throws tag in function comment
Loading history...
432
     */
0 ignored issues
show
Coding Style introduced by
Expected 2 @throws tag(s) in function comment; 1 found
Loading history...
433 838
    protected function runOrReconnect(Closure $callback)
434
    {
435
        try {
436
            try {
437 838
                return $callback();
438 33
            } catch (DoctrineDBALException $exception) {
439 33
                if ($this->causedByLostConnection($exception->getPrevious())) {
440
                    // Should check for active transaction.
441
                    // Only reconnect the start transaction.
442
                    // Should raise exception during transaction.
443 2
                    $this->close();
444 2
                    $this->connect();
445
446 2
                    return $callback();
447
                }
448
449 31
                throw $exception;
450
            }
451 31
        } catch (DoctrineDBALException $e) {
452 31
            throw new DBALException('Error on execute : '.$e->getMessage(), $e->getCode(), $e);
453
        }
454
    }
455
}
456