Passed
Push — master ( 16457d...d8118d )
by Ondřej
03:26
created

Connection   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 296
Duplicated Lines 0 %

Coupling/Cohesion

Components 6
Dependencies 10

Importance

Changes 0
Metric Value
wmc 47
lcom 6
cbo 10
dl 0
loc 296
rs 7.3617
c 0
b 0
f 0

47 Methods

Rating   Name   Duplication   Size   Complexity  
A getBackendPID() 0 4 1
A notify() 0 4 1
A listen() 0 4 1
A unlisten() 0 4 1
A unlistenAll() 0 4 1
A pollNotification() 0 4 1
A getName() 0 4 1
A getConfig() 0 4 1
A getParameters() 0 4 1
A isConnected() 0 4 1
A isConnectedWait() 0 4 1
A connect() 0 4 1
A connectWait() 0 4 1
A disconnect() 0 4 1
A registerConnectStartHook() 0 4 1
A registerPreDisconnectHook() 0 4 1
A registerPostDisconnectHook() 0 4 1
A getTypeRegister() 0 4 1
A getTypeDictionary() 0 4 1
A flushTypeDictionary() 0 4 1
A __construct() 0 11 1
A setTypeControlOption() 0 4 1
A unsetTypeControlOption() 0 4 1
A query() 0 4 1
A querySingleTuple() 0 4 1
A querySingleColumn() 0 4 1
A querySingleValue() 0 4 1
A command() 0 4 1
A rawQuery() 0 4 1
A rawCommand() 0 4 1
A executeStatement() 0 4 1
A runScript() 0 4 1
A getStatementExceptionFactory() 0 4 1
A inTransaction() 0 4 1
A startTransaction() 0 4 1
A setupSubsequentTransactions() 0 4 1
A getDefaultTxConfig() 0 4 1
A commitPreparedTransaction() 0 4 1
A rollbackPreparedTransaction() 0 4 1
A listPreparedTransactions() 0 4 1
A addTransactionControlObserver() 0 4 1
A removeTransactionControlObserver() 0 4 1
A removeAllTransactionControlObservers() 0 4 1
A isCacheEnabled() 0 4 1
A cachePermanently() 0 5 1
A getCached() 0 5 1
A flushCache() 0 5 1

How to fix   Complexity   

Complex Class

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

1
<?php
2
declare(strict_types=1);
3
namespace Ivory\Connection;
4
5
use Ivory\Connection\Config\ConnConfig;
6
use Ivory\Connection\Config\IConnConfig;
7
use Ivory\Exception\StatementExceptionFactory;
8
use Ivory\Ivory;
9
use Ivory\Relation\IColumn;
10
use Ivory\Relation\ITuple;
11
use Ivory\Result\ICommandResult;
12
use Ivory\Result\IQueryResult;
13
use Ivory\Result\IResult;
14
use Ivory\Type\ITypeDictionary;
15
use Ivory\Type\TypeRegister;
16
use Ivory\Utils\NotSerializable;
17
18
// TODO: consider renaming to Database or Session or... - to reflect it is mere a facade, the single entry point
19
class Connection implements IConnection
20
{
21
    use NotSerializable; // TODO: implement connection serialization instead of giving up
22
23
    private $name;
24
    private $connCtl;
25
    private $typeCtl;
26
    private $stmtExec;
27
    private $txCtl;
28
    private $ipcCtl;
29
    private $cacheCtl;
30
31
    private $config;
32
33
34
    /**
35
     * @param string $name name for the connection
36
     * @param ConnectionParameters|array|string $params either a connection parameters object, or an associative array
37
     *                                                    of parameters for {@link ConnectionParameters::__construct()},
38
     *                                                    or a URL for {@link ConnectionParameters::fromUrl()},
39
     *                                                    or a PostgreSQL connection string (see {@link pg_connect()})
40
     */
41
    public function __construct(string $name, $params)
42
    {
43
        $this->name = $name;
44
        $this->connCtl = new ConnectionControl($this, $params); // TODO: extract all usages of ConnectionControl::requireConnection() - consider introducing an interface specifying the method, named like PGSQLDriver or ConnectionManager or ConnectionPool
45
        $this->typeCtl = new TypeControl($this, $this->connCtl);
46
        $this->stmtExec = new StatementExecution($this->connCtl, $this->typeCtl);
47
        $this->txCtl = new TransactionControl($this->connCtl, $this->stmtExec, $this);
48
        $this->ipcCtl = new IPCControl($this->connCtl, $this->stmtExec);
49
        $this->config = new ConnConfig($this->connCtl, $this->stmtExec, $this->txCtl);
50
        $this->cacheCtl = Ivory::getCoreFactory()->createCacheControl($this); // TODO: consider moving cacheCtl initialization out of Connection itself (let the core factory set it up), or do not hold cache control here but rather besides the connection register at Ivory
51
    }
52
53
    final public function getName(): string
54
    {
55
        return $this->name;
56
    }
57
58
    final public function getConfig(): IConnConfig
59
    {
60
        return $this->config;
61
    }
62
63
64
    //region Connection Control
65
66
    public function getParameters(): ConnectionParameters
67
    {
68
        return $this->connCtl->getParameters();
69
    }
70
71
    public function isConnected(): ?bool
72
    {
73
        return $this->connCtl->isConnected();
74
    }
75
76
    public function isConnectedWait(): ?bool
77
    {
78
        return $this->connCtl->isConnectedWait();
79
    }
80
81
    public function connect(?\Closure $initProcedure = null): bool
82
    {
83
        return $this->connCtl->connect($initProcedure);
84
    }
85
86
    public function connectWait(): bool
87
    {
88
        return $this->connCtl->connectWait();
89
    }
90
91
    public function disconnect(): bool
92
    {
93
        return $this->connCtl->disconnect();
94
    }
95
96
    public function registerConnectStartHook(\Closure $closure): void
97
    {
98
        $this->connCtl->registerConnectStartHook($closure);
99
    }
100
101
    public function registerPreDisconnectHook(\Closure $closure): void
102
    {
103
        $this->connCtl->registerPreDisconnectHook($closure);
104
    }
105
106
    public function registerPostDisconnectHook(\Closure $closure): void
107
    {
108
        $this->connCtl->registerPostDisconnectHook($closure);
109
    }
110
111
    //endregion
112
113
    //region Type Control
114
115
    public function getTypeRegister(): TypeRegister
116
    {
117
        return $this->typeCtl->getTypeRegister();
118
    }
119
120
    public function getTypeDictionary(): ITypeDictionary
121
    {
122
        return $this->typeCtl->getTypeDictionary();
123
    }
124
125
    public function flushTypeDictionary(): void
126
    {
127
        $this->typeCtl->flushTypeDictionary();
128
    }
129
130
    public function setTypeControlOption(int $option): void
131
    {
132
        $this->typeCtl->setTypeControlOption($option);
133
    }
134
135
    public function unsetTypeControlOption(int $option): void
136
    {
137
        $this->typeCtl->unsetTypeControlOption($option);
138
    }
139
140
    //endregion
141
142
    //region Statement Execution
143
144
    public function query($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams): IQueryResult
145
    {
146
        return $this->stmtExec->query($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams);
147
    }
148
149
    public function querySingleTuple($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams): ITuple
150
    {
151
        return $this->stmtExec->querySingleTuple($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams);
152
    }
153
154
    public function querySingleColumn($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams): IColumn
155
    {
156
        return $this->stmtExec->querySingleColumn($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams);
157
    }
158
159
    public function querySingleValue($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams)
160
    {
161
        return $this->stmtExec->querySingleValue($sqlFragmentPatternOrRelationDefinition, ...$fragmentsAndParams);
162
    }
163
164
    public function command($sqlFragmentPatternOrCommand, ...$fragmentsAndParams): ICommandResult
165
    {
166
        return $this->stmtExec->command($sqlFragmentPatternOrCommand, ...$fragmentsAndParams);
167
    }
168
169
    public function rawQuery(string $sqlQuery): IQueryResult
170
    {
171
        return $this->stmtExec->rawQuery($sqlQuery);
172
    }
173
174
    public function rawCommand(string $sqlCommand): ICommandResult
175
    {
176
        return $this->stmtExec->rawCommand($sqlCommand);
177
    }
178
179
    public function executeStatement($sqlStatement): IResult
180
    {
181
        return $this->stmtExec->executeStatement($sqlStatement);
182
    }
183
184
    public function runScript(string $sqlScript): array
185
    {
186
        return $this->stmtExec->runScript($sqlScript);
187
    }
188
189
    public function getStatementExceptionFactory(): StatementExceptionFactory
190
    {
191
        return $this->stmtExec->getStatementExceptionFactory();
192
    }
193
194
    //endregion
195
196
    //region Transaction Control
197
198
    public function inTransaction(): bool
199
    {
200
        return $this->txCtl->inTransaction();
201
    }
202
203
    public function startTransaction($transactionOptions = 0): ITxHandle
204
    {
205
        return $this->txCtl->startTransaction($transactionOptions);
206
    }
207
208
    public function setupSubsequentTransactions($transactionOptions): void
209
    {
210
        $this->txCtl->setupSubsequentTransactions($transactionOptions);
211
    }
212
213
    public function getDefaultTxConfig(): TxConfig
214
    {
215
        return $this->txCtl->getDefaultTxConfig();
216
    }
217
218
    public function commitPreparedTransaction(string $name): void
219
    {
220
        $this->txCtl->commitPreparedTransaction($name);
221
    }
222
223
    public function rollbackPreparedTransaction(string $name): void
224
    {
225
        $this->txCtl->rollbackPreparedTransaction($name);
226
    }
227
228
    public function listPreparedTransactions(): IQueryResult
229
    {
230
        return $this->txCtl->listPreparedTransactions();
231
    }
232
233
    //endregion
234
235
    //region Transaction observing
236
237
    public function addTransactionControlObserver(ITransactionControlObserver $observer): void
238
    {
239
        $this->txCtl->addObserver($observer);
240
    }
241
242
    public function removeTransactionControlObserver(ITransactionControlObserver $observer): void
243
    {
244
        $this->txCtl->removeObserver($observer);
245
    }
246
247
    public function removeAllTransactionControlObservers(): void
248
    {
249
        $this->txCtl->removeAllObservers();
250
    }
251
252
    //endregion
253
254
    //region IPC Control
255
256
    public function getBackendPID(): int
257
    {
258
        return $this->ipcCtl->getBackendPID();
259
    }
260
261
    public function notify(string $channel, ?string $payload = null): void
262
    {
263
        $this->ipcCtl->notify($channel, $payload);
264
    }
265
266
    public function listen(string $channel): void
267
    {
268
        $this->ipcCtl->listen($channel);
269
    }
270
271
    public function unlisten(string $channel): void
272
    {
273
        $this->ipcCtl->unlisten($channel);
274
    }
275
276
    public function unlistenAll(): void
277
    {
278
        $this->ipcCtl->unlistenAll();
279
    }
280
281
    public function pollNotification(): ?Notification
282
    {
283
        return $this->ipcCtl->pollNotification();
284
    }
285
286
    //endregion
287
288
    //region Cache Control
289
290
    public function isCacheEnabled(): bool
291
    {
292
        return $this->cacheCtl->isCacheEnabled();
293
    }
294
295
    public function cachePermanently(string $cacheKey, $object): bool
296
    {
297
        /** @noinspection PhpUnhandledExceptionInspection PhpStorm bug WI-38168 */
298
        return $this->cacheCtl->cachePermanently($cacheKey, $object);
299
    }
300
301
    public function getCached(string $cacheKey)
302
    {
303
        /** @noinspection PhpUnhandledExceptionInspection PhpStorm bug WI-38168 */
304
        return $this->cacheCtl->getCached($cacheKey);
305
    }
306
307
    public function flushCache(string $cacheKey): bool
308
    {
309
        /** @noinspection PhpUnhandledExceptionInspection PhpStorm bug WI-38168 */
310
        return $this->cacheCtl->flushCache($cacheKey);
311
    }
312
313
    //endregion
314
}
315