PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.5.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.5.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
fluent-community / vendor / wpfluent / framework / src / WPFluent / Database / Concerns / ManagesTransactions.php

ManagesTransactions.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.5.0, at vendor/wpfluent/framework/src/WPFluent/Database/Concerns/ManagesTransactions.php

306 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\Framework\Database\Concerns;
4
5 use Closure;
6 use Throwable;
7 use RuntimeException;
8
9 trait ManagesTransactions
10 {
11 /**
12 * Execute a Closure within a transaction.
13 *
14 * @template TReturn
15 * @param \Closure(static): TReturn $callback
16 * @param int $attempts
17 * @return TReturn
18 *
19 * @throws \Throwable
20 */
21 public function transaction(Closure $callback, $attempts = 1)
22 {
23 for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
24
25 $this->beginTransaction();
26
27 try {
28 $result = $callback($this);
29 } catch (Throwable $e) {
30 $this->handleTransactionException($e, $currentAttempt, $attempts);
31 continue;
32 }
33
34 $levelBeingCommitted = $this->transactions;
35
36 try {
37 $this->commit();
38 } catch (Throwable $e) {
39 $this->handleCommitTransactionException($e, $currentAttempt, $attempts);
40 continue;
41 }
42
43 if ($this->transactionsManager) {
44 $this->transactionsManager->commit(
45 $this->getName(),
46 $levelBeingCommitted,
47 $this->transactions
48 );
49 }
50
51 return $result;
52 }
53 }
54
55 /**
56 * Begin transaction or create savepoint.
57 */
58 public function beginTransaction()
59 {
60 if ($this->inTransaction()) {
61
62 $this->transactions++;
63
64 if ($this->supportsSavepoints()) {
65 $this->createSavepoint();
66 }
67
68 if ($this->transactionsManager) {
69 $this->transactionsManager->begin(
70 $this->getName(),
71 $this->transactions
72 );
73 }
74
75 return;
76 }
77
78 $this->transactions++;
79
80 $this->createTransaction();
81
82 if ($this->transactionsManager) {
83 $this->transactionsManager->begin(
84 $this->getName(),
85 $this->transactions
86 );
87 }
88 }
89
90 /**
91 * Create root transaction.
92 */
93 protected function createTransaction()
94 {
95 try {
96 if ($this->isSqlite()) {
97 $this->unprepared('BEGIN;');
98 } else {
99 $this->unprepared('START TRANSACTION;');
100 }
101 } catch (Throwable $e) {
102 $this->handleBeginTransactionException($e);
103 }
104 }
105
106 /**
107 * Create savepoint.
108 */
109 protected function createSavepoint()
110 {
111 $name = $this->getSavepointName($this->transactions);
112 $this->unprepared("SAVEPOINT {$name};");
113 }
114
115 /**
116 * Commit transaction or release savepoint.
117 */
118 public function commit()
119 {
120 if ($this->transactions === 0) {
121 return;
122 }
123
124 if ($this->transactions === 1) {
125
126 $this->unprepared('COMMIT;');
127
128 } elseif ($this->supportsSavepoints()) {
129
130 $name = $this->getSavepointName($this->transactions);
131 $this->unprepared("RELEASE SAVEPOINT {$name};");
132 }
133
134 [$levelBeingCommitted, $this->transactions] = [
135 $this->transactions,
136 max(0, $this->transactions - 1),
137 ];
138
139 if ($this->transactionsManager) {
140 $this->transactionsManager->commit(
141 $this->getName(),
142 $levelBeingCommitted,
143 $this->transactions
144 );
145 }
146 }
147
148 /**
149 * Rollback transaction.
150 */
151 public function rollBack($toLevel = null)
152 {
153 $toLevel = is_null($toLevel)
154 ? $this->transactions - 1
155 : $toLevel;
156
157 if ($toLevel < 0 || $toLevel >= $this->transactions) {
158 return;
159 }
160
161 try {
162 $this->performRollBack($toLevel);
163 } catch (Throwable $e) {
164 $this->handleRollBackException($e);
165 }
166
167 $this->transactions = $toLevel;
168
169 if ($this->transactionsManager) {
170 $this->transactionsManager->rollback(
171 $this->getName(),
172 $this->transactions
173 );
174 }
175 }
176
177 /**
178 * Perform rollback.
179 */
180 protected function performRollBack($toLevel)
181 {
182 if ($toLevel === 0) {
183
184 $this->unprepared('ROLLBACK;');
185
186 } elseif ($this->supportsSavepoints()) {
187
188 $name = $this->getSavepointName($toLevel + 1);
189 $this->unprepared("ROLLBACK TO SAVEPOINT {$name};");
190 }
191 }
192
193 /**
194 * Determine if savepoints are supported.
195 */
196 protected function supportsSavepoints()
197 {
198 // SQLite under WordPress does NOT support savepoints
199 if ($this->isSqlite()) {
200 return false;
201 }
202
203 return true;
204 }
205
206 /**
207 * Handle transaction exception.
208 */
209 protected function handleTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
210 {
211 $this->rollBack();
212 throw $e;
213 }
214
215 /**
216 * Handle commit exception.
217 */
218 protected function handleCommitTransactionException(Throwable $e, $currentAttempt, $maxAttempts)
219 {
220 $this->transactions = max(0, $this->transactions - 1);
221
222 if ($this->causedByLostConnection($e)) {
223 $this->transactions = 0;
224 }
225
226 throw $e;
227 }
228
229 /**
230 * Handle begin exception.
231 */
232 protected function handleBeginTransactionException(Throwable $e)
233 {
234 if ($this->causedByLostConnection($e)) {
235 $this->reconnect();
236 } else {
237 throw $e;
238 }
239 }
240
241 /**
242 * Handle rollback exception.
243 */
244 protected function handleRollBackException(Throwable $e)
245 {
246 if ($this->causedByLostConnection($e)) {
247 $this->transactions = 0;
248 }
249
250 throw $e;
251 }
252
253 /**
254 * Get savepoint name.
255 */
256 protected function getSavepointName($level)
257 {
258 return 'trans' . $level;
259 }
260
261 /**
262 * Transaction nesting level.
263 */
264 public function transactionLevel()
265 {
266 return $this->transactions;
267 }
268
269 /**
270 * After commit callback.
271 */
272 public function afterCommit($callback)
273 {
274 if ($this->transactionsManager) {
275 return $this->transactionsManager->addCallback($callback);
276 }
277
278 throw new RuntimeException('Transactions Manager has not been set.');
279 }
280
281 /**
282 * In transaction?
283 */
284 public function inTransaction()
285 {
286 return $this->transactions > 0;
287 }
288
289 /**
290 * Set transaction manager.
291 */
292 public function setTransactionManager($manager)
293 {
294 $this->transactionsManager = $manager;
295 return $this;
296 }
297
298 /**
299 * Unset transaction manager.
300 */
301 public function unsetTransactionManager()
302 {
303 $this->transactionsManager = null;
304 }
305 }
306