| Total Complexity | 52 |
| Total Lines | 284 |
| Duplicated Lines | 0 % |
| Changes | 2 | ||
| Bugs | 0 | Features | 0 |
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.
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 |
||
| 17 | abstract class Connection implements ConnectionInterface |
||
| 18 | { |
||
| 19 | use LoggerAwareTrait; |
||
| 20 | use ProfilerAwareTrait; |
||
| 21 | |||
| 22 | protected array $masters = []; |
||
| 23 | protected array $slaves = []; |
||
| 24 | protected ?ConnectionInterface $master = null; |
||
| 25 | protected ?ConnectionInterface $slave = null; |
||
| 26 | protected ?TransactionInterface $transaction = null; |
||
| 27 | private ?bool $emulatePrepare = null; |
||
| 28 | private bool $enableSavepoint = true; |
||
| 29 | private bool $enableSlaves = true; |
||
| 30 | private int $serverRetryInterval = 600; |
||
| 31 | private bool $shuffleMasters = true; |
||
| 32 | private string $tablePrefix = ''; |
||
| 33 | |||
| 34 | public function __construct(private QueryCache $queryCache) |
||
| 35 | { |
||
| 36 | } |
||
| 37 | |||
| 38 | public function areSlavesEnabled(): bool |
||
| 39 | { |
||
| 40 | return $this->enableSlaves; |
||
| 41 | } |
||
| 42 | |||
| 43 | public function beginTransaction(string $isolationLevel = null): TransactionInterface |
||
| 44 | { |
||
| 45 | $this->open(); |
||
| 46 | $this->transaction = $this->getTransaction(); |
||
| 47 | |||
| 48 | if ($this->transaction === null) { |
||
| 49 | $this->transaction = $this->createTransaction(); |
||
| 50 | } |
||
| 51 | |||
| 52 | if ($this->logger !== null) { |
||
| 53 | $this->transaction->setLogger($this->logger); |
||
| 54 | } |
||
| 55 | |||
| 56 | $this->transaction->begin($isolationLevel); |
||
| 57 | |||
| 58 | return $this->transaction; |
||
| 59 | } |
||
| 60 | |||
| 61 | public function cache(callable $callable, int $duration = null, Dependency $dependency = null): mixed |
||
| 62 | { |
||
| 63 | $this->queryCache->setInfo( |
||
| 64 | [$duration ?? $this->queryCache->getDuration(), $dependency] |
||
| 65 | ); |
||
| 66 | $result = $callable($this); |
||
| 67 | $this->queryCache->removeLastInfo(); |
||
| 68 | return $result; |
||
| 69 | } |
||
| 70 | |||
| 71 | public function getEmulatePrepare(): ?bool |
||
| 72 | { |
||
| 73 | return $this->emulatePrepare; |
||
| 74 | } |
||
| 75 | |||
| 76 | public function getLastInsertID(string $sequenceName = ''): string |
||
| 77 | { |
||
| 78 | return $this->getSchema()->getLastInsertID($sequenceName); |
||
| 79 | } |
||
| 80 | |||
| 81 | public function getMaster(): ?self |
||
| 82 | { |
||
| 83 | if ($this->master === null) { |
||
| 84 | $this->master = $this->shuffleMasters |
||
| 85 | ? $this->openFromPool($this->masters) |
||
| 86 | : $this->openFromPoolSequentially($this->masters); |
||
| 87 | } |
||
| 88 | |||
| 89 | return $this->master; |
||
|
|
|||
| 90 | } |
||
| 91 | |||
| 92 | public function getSlave(bool $fallbackToMaster = true): ?self |
||
| 93 | { |
||
| 94 | if (!$this->enableSlaves) { |
||
| 95 | return $fallbackToMaster ? $this : null; |
||
| 96 | } |
||
| 97 | |||
| 98 | if ($this->slave === null) { |
||
| 99 | $this->slave = $this->openFromPool($this->slaves); |
||
| 100 | } |
||
| 101 | |||
| 102 | return $this->slave === null && $fallbackToMaster ? $this : $this->slave; |
||
| 103 | } |
||
| 104 | |||
| 105 | public function getTablePrefix(): string |
||
| 106 | { |
||
| 107 | return $this->tablePrefix; |
||
| 108 | } |
||
| 109 | |||
| 110 | public function getTableSchema(string $name, bool $refresh = false): ?TableSchema |
||
| 111 | { |
||
| 112 | return $this->getSchema()->getTableSchema($name, $refresh); |
||
| 113 | } |
||
| 114 | |||
| 115 | public function getTransaction(): ?TransactionInterface |
||
| 116 | { |
||
| 117 | return $this->transaction && $this->transaction->isActive() ? $this->transaction : null; |
||
| 118 | } |
||
| 119 | |||
| 120 | public function isSavepointEnabled(): bool |
||
| 121 | { |
||
| 122 | return $this->enableSavepoint; |
||
| 123 | } |
||
| 124 | |||
| 125 | public function noCache(callable $callable): mixed |
||
| 126 | { |
||
| 127 | $queryCache = $this->queryCache; |
||
| 128 | $queryCache->setInfo(false); |
||
| 129 | $result = $callable($this); |
||
| 130 | $queryCache->removeLastInfo(); |
||
| 131 | return $result; |
||
| 132 | } |
||
| 133 | |||
| 134 | public function setEmulatePrepare(bool $value): void |
||
| 137 | } |
||
| 138 | |||
| 139 | public function setEnableSavepoint(bool $value): void |
||
| 140 | { |
||
| 141 | $this->enableSavepoint = $value; |
||
| 142 | } |
||
| 143 | |||
| 144 | public function setEnableSlaves(bool $value): void |
||
| 145 | { |
||
| 146 | $this->enableSlaves = $value; |
||
| 147 | } |
||
| 148 | |||
| 149 | public function setMaster(string $key, ConnectionInterface $master): void |
||
| 150 | { |
||
| 151 | $this->masters[$key] = $master; |
||
| 152 | } |
||
| 153 | |||
| 154 | public function setServerRetryInterval(int $value): void |
||
| 155 | { |
||
| 156 | $this->serverRetryInterval = $value; |
||
| 157 | } |
||
| 158 | |||
| 159 | public function setShuffleMasters(bool $value): void |
||
| 162 | } |
||
| 163 | |||
| 164 | public function setSlave(string $key, ConnectionInterface $slave): void |
||
| 165 | { |
||
| 166 | $this->slaves[$key] = $slave; |
||
| 167 | } |
||
| 168 | |||
| 169 | public function setTablePrefix(string $value): void |
||
| 170 | { |
||
| 171 | $this->tablePrefix = $value; |
||
| 172 | } |
||
| 173 | |||
| 174 | public function transaction(callable $callback, string $isolationLevel = null): mixed |
||
| 193 | } |
||
| 194 | |||
| 195 | public function useMaster(callable $callback): mixed |
||
| 196 | { |
||
| 197 | if ($this->enableSlaves) { |
||
| 198 | $this->enableSlaves = false; |
||
| 199 | |||
| 200 | try { |
||
| 201 | $result = $callback($this); |
||
| 202 | } catch (Throwable $e) { |
||
| 203 | $this->enableSlaves = true; |
||
| 204 | |||
| 205 | throw $e; |
||
| 206 | } |
||
| 207 | $this->enableSlaves = true; |
||
| 208 | } else { |
||
| 209 | $result = $callback($this); |
||
| 210 | } |
||
| 211 | |||
| 212 | return $result; |
||
| 213 | } |
||
| 214 | |||
| 215 | /** |
||
| 216 | * Opens the connection to a server in the pool. |
||
| 217 | * |
||
| 218 | * This method implements the load balancing among the given list of the servers. |
||
| 219 | * |
||
| 220 | * Connections will be tried in random order. |
||
| 221 | * |
||
| 222 | * @param array $pool The list of connection configurations in the server pool. |
||
| 223 | * |
||
| 224 | * @return static|null The opened DB connection, or `null` if no server is available. |
||
| 225 | */ |
||
| 226 | protected function openFromPool(array $pool): ?self |
||
| 227 | { |
||
| 228 | shuffle($pool); |
||
| 229 | return $this->openFromPoolSequentially($pool); |
||
| 230 | } |
||
| 231 | |||
| 232 | /** |
||
| 233 | * Opens the connection to a server in the pool. |
||
| 234 | * |
||
| 235 | * This method implements the load balancing among the given list of the servers. |
||
| 236 | * |
||
| 237 | * Connections will be tried in sequential order. |
||
| 238 | * |
||
| 239 | * @param array $pool |
||
| 240 | * |
||
| 241 | * @return static|null The opened DB connection, or `null` if no server is available. |
||
| 242 | */ |
||
| 243 | protected function openFromPoolSequentially(array $pool): ?self |
||
| 280 | } |
||
| 281 | |||
| 282 | /** |
||
| 283 | * Rolls back given {@see TransactionInterface} object if it's still active and level match. In some cases rollback |
||
| 284 | * can fail, so this method is fail-safe. Exceptions thrown from rollback will be caught and just logged with |
||
| 285 | * {@see logger->log()}. |
||
| 286 | * |
||
| 287 | * @param TransactionInterface $transaction TransactionInterface object given from {@see beginTransaction()}. |
||
| 288 | * @param int $level TransactionInterface level just after {@see beginTransaction()} call. |
||
| 289 | */ |
||
| 290 | private function rollbackTransactionOnLevel(TransactionInterface $transaction, int $level): void |
||
| 291 | { |
||
| 301 | /** hide this exception to be able to continue throwing original exception outside */ |
||
| 302 | } |
||
| 303 | } |
||
| 304 | } |
||
| 305 | } |
||
| 306 | } |
||
| 307 |