Test Failed
Pull Request — master (#46)
by Jean-Christophe
08:20
created

DatabaseTransactionsTrait::commitToLevel()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Ubiquity\db\traits;
4
5
use Ubiquity\exceptions\DBException;
6
7
/**
8
 * Manages database transactions.
9
 * Ubiquity\db\traits$DatabaseTransactionsTrait
10
 * This class is part of Ubiquity
11
 *
12
 * @author jcheron <[email protected]>
13
 * @version 1.0.0
14
 * @property \PDO $pdoObject
15
 * @property string $dbType
16
 */
17
trait DatabaseTransactionsTrait {
18
	protected static $savepointsDrivers = [ 'pgsql' => true,'mysql' => true,'sqlite' => true ];
19
	protected $transactionLevel = 0;
20
21
	protected function nestable() {
22
		return isset ( self::$savepointsDrivers [$this->dbType] );
23
	}
24
25
	/**
26
	 * Initiates a transaction
27
	 *
28
	 * @return boolean true on success or false on failure
29
	 */
30
	public function beginTransaction() {
31
		if ($this->transactionLevel == 0 || ! $this->nestable ()) {
32
			$ret = $this->pdoObject->beginTransaction ();
33
			$this->transactionLevel ++;
34
			return $ret;
35
		}
36
		$this->pdoObject->exec ( 'SAVEPOINT LEVEL' . $this->transactionLevel );
37
		$this->transactionLevel ++;
38
		return true;
39
	}
40
41
	/**
42
	 * Commits a transaction
43
	 *
44
	 * @return boolean true on success or false on failure
45
	 */
46
	public function commit() {
47
		$this->transactionLevel --;
48
		if ($this->transactionLevel == 0 || ! $this->nestable ()) {
49
			return $this->pdoObject->commit ();
50
		}
51
		$this->pdoObject->exec ( 'RELEASE SAVEPOINT LEVEL' . $this->transactionLevel );
52
		return true;
53
	}
54
55
	/**
56
	 * Commits nested transactions up to level $transactionLevel
57
	 *
58
	 * @param int $transactionLevel
59
	 */
60
	public function commitToLevel($transactionLevel) {
61
		while ( $this->transactionLevel > $transactionLevel ) {
62
			$this->commit ();
63
		}
64
	}
65
66
	/**
67
	 * Commits all nested transactions (up to level 0)
68
	 */
69
	public function commitAll() {
70
		$this->commitToLevel ( 0 );
71
	}
72
73
	/**
74
	 * Rolls back a transaction
75
	 *
76
	 * @return boolean true on success or false on failure
77
	 */
78
	public function rollBack() {
79
		$this->transactionLevel --;
80
81
		if ($this->transactionLevel == 0 || ! $this->nestable ()) {
82
			return $this->pdoObject->rollBack ();
83
		}
84
		$this->pdoObject->exec ( 'ROLLBACK TO SAVEPOINT LEVEL' . $this->transactionLevel );
85
		return true;
86
	}
87
88
	/**
89
	 * Rolls back nested transactions up to level $transactionLevel
90
	 *
91
	 * @param int $transactionLevel
92
	 */
93
	public function rollBackToLevel($transactionLevel) {
94
		while ( $this->transactionLevel > $transactionLevel ) {
95
			$this->rollBack ();
96
		}
97
	}
98
99
	/**
100
	 * Rolls back all nested transactions (up to level 0)
101
	 */
102
	public function rollBackAll() {
103
		$this->rollBackToLevel ( 0 );
104
	}
105
106
	/**
107
	 * Checks if inside a transaction
108
	 *
109
	 * @return boolean
110
	 */
111
	public function inTransaction() {
112
		return $this->pdoObject->inTransaction ();
113
	}
114
115
	/**
116
	 * Call a callback with an array of parameters in a transaction
117
	 *
118
	 * @param callable $callback
119
	 * @param mixed ...$parameters
120
	 * @throws \Exception
121
	 * @return mixed
122
	 */
123
	function callInTransaction($callback, ...$parameters) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
124
		if ($this->beginTransaction ()) {
125
			try {
126
				$ret = call_user_func_array ( $callback, $parameters );
127
			} catch ( \Exception $e ) {
128
				$this->rollBack ();
129
				throw $e;
130
			}
131
132
			if ($ret) {
133
				if (! $this->commit ())
134
					throw new DBException ( 'Transaction was not committed.' );
135
			} else {
136
				$this->rollBack ();
137
			}
138
139
			return $ret;
140
		}
141
		throw new DBException ( 'Transaction was not started.' );
142
	}
143
}
144