Passed
Push — master ( 128efe...35dbe9 )
by Jean-Christophe
07:22
created

DatabaseTransactionsTrait::inTransaction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 2
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace Ubiquity\db\traits;
4
5
use Ubiquity\exceptions\DBException;
6
use Ubiquity\log\Logger;
7
8
/**
9
 * Manages database transactions.
10
 * Ubiquity\db\traits$DatabaseTransactionsTrait
11
 * This class is part of Ubiquity
12
 *
13
 * @author jcheron <[email protected]>
14
 * @version 1.0.0
15
 * @property \PDO $pdoObject
16
 * @property string $dbType
17
 */
18
trait DatabaseTransactionsTrait {
19
	protected static $savepointsDrivers = [ 'pgsql' => true,'mysql' => true,'sqlite' => true ];
20
	protected $transactionLevel = 0;
21
22 4
	protected function nestable() {
23 4
		return isset ( self::$savepointsDrivers [$this->dbType] );
24
	}
25
26
	/**
27
	 * Initiates a transaction
28
	 *
29
	 * @return boolean true on success or false on failure
30
	 */
31 8
	public function beginTransaction() {
32 8
		if ($this->transactionLevel == 0 || ! $this->nestable ()) {
33 8
			$ret = $this->pdoObject->beginTransaction ();
34 8
			Logger::info ( 'Transactions', 'Start transaction', 'beginTransaction' );
35 8
			$this->transactionLevel ++;
36 8
			return $ret;
37
		}
38 4
		$this->pdoObject->exec ( 'SAVEPOINT LEVEL' . $this->transactionLevel );
39 4
		Logger::info ( 'Transactions', 'Savepoint level', 'beginTransaction', $this->transactionLevel );
40 4
		$this->transactionLevel ++;
41 4
		return true;
42
	}
43
44
	/**
45
	 * Commits a transaction
46
	 *
47
	 * @return boolean true on success or false on failure
48
	 */
49 4
	public function commit() {
50 4
		$this->transactionLevel --;
51 4
		if ($this->transactionLevel == 0 || ! $this->nestable ()) {
52 4
			Logger::info ( 'Transactions', 'Commit transaction', 'commit' );
53 4
			return $this->pdoObject->commit ();
54
		}
55 2
		$this->pdoObject->exec ( 'RELEASE SAVEPOINT LEVEL' . $this->transactionLevel );
56 2
		Logger::info ( 'Transactions', 'Release savepoint level', 'commit', $this->transactionLevel );
57 2
		return true;
58
	}
59
60
	/**
61
	 * Commits nested transactions up to level $transactionLevel
62
	 *
63
	 * @param int $transactionLevel
64
	 * @return boolean true on success or false on failure
65
	 */
66 1
	public function commitToLevel($transactionLevel) {
67 1
		$res = true;
68 1
		while ( $res && $this->transactionLevel > $transactionLevel ) {
69 1
			$res = $this->commit ();
70
		}
71 1
		return $res;
72
	}
73
74
	/**
75
	 * Commits all nested transactions (up to level 0)
76
	 *
77
	 * @return boolean true on success or false on failure
78
	 */
79 1
	public function commitAll() {
80 1
		return $this->commitToLevel ( 0 );
81
	}
82
83
	/**
84
	 * Rolls back a transaction
85
	 *
86
	 * @return boolean true on success or false on failure
87
	 */
88 3
	public function rollBack() {
89 3
		$this->transactionLevel --;
90
91 3
		if ($this->transactionLevel == 0 || ! $this->nestable ()) {
92 3
			Logger::info ( 'Transactions', 'Rollback transaction', 'rollBack' );
93 3
			return $this->pdoObject->rollBack ();
94
		}
95 2
		$this->pdoObject->exec ( 'ROLLBACK TO SAVEPOINT LEVEL' . $this->transactionLevel );
96 2
		Logger::info ( 'Transactions', 'Rollback to savepoint level', 'rollBack', $this->transactionLevel );
97 2
		return true;
98
	}
99
100
	/**
101
	 * Rolls back nested transactions up to level $transactionLevel
102
	 *
103
	 * @param int $transactionLevel
104
	 * @return boolean true on success or false on failure
105
	 */
106 1
	public function rollBackToLevel($transactionLevel) {
107 1
		$res = true;
108 1
		while ( $res && $this->transactionLevel > $transactionLevel ) {
109 1
			$res = $this->rollBack ();
110
		}
111 1
		return $res;
112
	}
113
114
	/**
115
	 * Rolls back all nested transactions (up to level 0)
116
	 *
117
	 * @return boolean true on success or false on failure
118
	 */
119 1
	public function rollBackAll() {
120 1
		return $this->rollBackToLevel ( 0 );
121
	}
122
123
	/**
124
	 * Checks if inside a transaction
125
	 *
126
	 * @return boolean
127
	 */
128
	public function inTransaction() {
129
		return $this->pdoObject->inTransaction ();
130
	}
131
132
	/**
133
	 * Call a callback with an array of parameters in a transaction
134
	 *
135
	 * @param callable $callback
136
	 * @param mixed ...$parameters
137
	 * @throws \Exception
138
	 * @return mixed
139
	 */
140
	public function callInTransaction($callback, ...$parameters) {
141
		if ($this->beginTransaction ()) {
142
			try {
143
				$ret = call_user_func_array ( $callback, $parameters );
144
			} catch ( \Exception $e ) {
145
				$this->rollBack ();
146
				throw $e;
147
			}
148
149
			if ($ret) {
150
				if (! $this->commit ()) {
151
					throw new DBException ( 'Transaction was not committed.' );
152
				}
153
			} else {
154
				$this->rollBack ();
155
			}
156
157
			return $ret;
158
		}
159
		throw new DBException ( 'Transaction was not started.' );
160
	}
161
}
162