INFRA-132 - Civi - PHPStorm cleanup
[civicrm-core.git] / Civi / Core / Transaction / Frame.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 namespace Civi\Core\Transaction;
29
30 /**
31 * A "frame" is a layer in a series of nested transactions. Generally,
32 * the outermost frame is a normal SQL transaction (BEGIN/ROLLBACK/COMMIT)
33 * and any nested frames are SQL savepoints (SAVEPOINT foo/ROLLBACK TO SAVEPOINT).
34 *
35 * @package Civi
36 * @copyright CiviCRM LLC (c) 2004-2014
37 */
38 class Frame {
39
40 const F_NEW = 0, F_ACTIVE = 1, F_DONE = 2, F_FORCED = 3;
41
42 /**
43 * @var \CRM_Core_DAO
44 */
45 private $dao;
46
47 /**
48 * @var string|null e.g. "BEGIN" or "SAVEPOINT foo"
49 */
50 private $beginStmt;
51
52 /**
53 * @var string|null e.g. "COMMIT"
54 */
55 private $commitStmt;
56
57 /**
58 * @var string|null e.g. "ROLLBACK" or "ROLLBACK TO SAVEPOINT foo"
59 */
60 private $rollbackStmt;
61
62 /**
63 * @var int
64 */
65 private $refCount = 0;
66 private $callbacks;
67 private $doCommit = TRUE;
68
69 /**
70 * @var int
71 */
72 private $state = self::F_NEW;
73
74 /**
75 * @param \CRM_Core_DAO $dao
76 * @param string|null $beginStmt e.g. "BEGIN" or "SAVEPOINT foo"
77 * @param string|null $commitStmt e.g. "COMMIT"
78 * @param string|null $rollbackStmt e.g. "ROLLBACK" or "ROLLBACK TO SAVEPOINT foo"
79 */
80 public function __construct($dao, $beginStmt, $commitStmt, $rollbackStmt) {
81 $this->dao = $dao;
82 $this->beginStmt = $beginStmt;
83 $this->commitStmt = $commitStmt;
84 $this->rollbackStmt = $rollbackStmt;
85
86 $this->callbacks = array(
87 \CRM_Core_Transaction::PHASE_PRE_COMMIT => array(),
88 \CRM_Core_Transaction::PHASE_POST_COMMIT => array(),
89 \CRM_Core_Transaction::PHASE_PRE_ROLLBACK => array(),
90 \CRM_Core_Transaction::PHASE_POST_ROLLBACK => array(),
91 );
92 }
93
94 public function inc() {
95 $this->refCount++;
96 }
97
98 public function dec() {
99 $this->refCount--;
100 }
101
102 public function isEmpty() {
103 return ($this->refCount == 0);
104 }
105
106 public function isRollbackOnly() {
107 return !$this->doCommit;
108 }
109
110 public function setRollbackOnly() {
111 $this->doCommit = FALSE;
112 }
113
114 public function begin() {
115 assert('$this->state === self::F_NEW');
116 $this->state = self::F_ACTIVE;
117 if ($this->beginStmt) {
118 $this->dao->query($this->beginStmt);
119 }
120 }
121
122 /**
123 * @param int $newState
124 * @void
125 */
126 public function finish($newState = self::F_DONE) {
127 if ($this->state == self::F_FORCED) {
128 return;
129 }
130 assert('$this->state === self::F_ACTIVE');
131 $this->state = $newState;
132
133 if ($this->doCommit) {
134 $this->invokeCallbacks(\CRM_Core_Transaction::PHASE_PRE_COMMIT);
135 if ($this->commitStmt) {
136 $this->dao->query($this->commitStmt);
137 }
138 $this->invokeCallbacks(\CRM_Core_Transaction::PHASE_POST_COMMIT);
139 }
140 else {
141 $this->invokeCallbacks(\CRM_Core_Transaction::PHASE_PRE_ROLLBACK);
142 if ($this->rollbackStmt) {
143 $this->dao->query($this->rollbackStmt);
144 }
145 $this->invokeCallbacks(\CRM_Core_Transaction::PHASE_POST_ROLLBACK);
146 }
147 }
148
149 public function forceRollback() {
150 $this->setRollbackOnly();
151 $this->finish(self::F_FORCED);
152 }
153
154 /**
155 * Add a transaction callback
156 *
157 * Pre-condition: isActive()
158 *
159 * @param int $phase
160 * A constant; one of: self::PHASE_{PRE,POST}_{COMMIT,ROLLBACK}.
161 * @param mixed $callback
162 * A PHP callback.
163 * @param array|NULL $params Optional values to pass to callback.
164 * See php manual call_user_func_array for details.
165 */
166 public function addCallback($phase, $callback, $params = NULL, $id = NULL) {
167 if ($id) {
168 $this->callbacks[$phase][$id] = array(
169 'callback' => $callback,
170 'parameters' => (is_array($params) ? $params : array($params))
171 );
172 }
173 else {
174 $this->callbacks[$phase][] = array(
175 'callback' => $callback,
176 'parameters' => (is_array($params) ? $params : array($params))
177 );
178 }
179 }
180
181 /**
182 * @param int $phase
183 */
184 public function invokeCallbacks($phase) {
185 if (is_array($this->callbacks[$phase])) {
186 foreach ($this->callbacks[$phase] as $cb) {
187 call_user_func_array($cb['callback'], $cb['parameters']);
188 }
189 }
190 }
191
192 }