+ private static $inTransaction = false;
+ public static function startTransaction()
+ {
+ if (self::$inTransaction) {
+ throw new XDBException('START TRANSACTION', 'Already in a transaction');
+ }
+ self::$inTransaction = true;
+ self::rawExecute('SET AUTOCOMMIT = 0');
+ self::rawExecute('START TRANSACTION');
+ }
+
+ public static function commit()
+ {
+ self::rawExecute('COMMIT');
+ self::rawExecute('SET AUTOCOMMIT = 1');
+ self::$inTransaction = false;
+ }
+
+ public static function rollback()
+ {
+ self::rawExecute('ROLLBACK');
+ self::rawExecute('SET AUTOCOMMIT = 1');
+ self::$inTransaction = false;
+ }
+
+ public static function runTransactionV($callback, array $args)
+ {
+ self::startTransaction();
+ try {
+ if (call_user_func_array($callback, $args)) {
+ self::commit();
+ return true;
+ } else {
+ self::rollback();
+ return false;
+ }
+ } catch (Exception $e) {
+ self::rollback();
+ throw $e;
+ }
+ }
+
+ /** This function takes a callback followed by the arguments to be passed to the callback
+ * as arguments. It starts a transaction and execute the callback. If the callback fails
+ * (return false or raise an exception), the transaction is rollbacked, if the callback
+ * succeeds (return true), the transaction is committed.
+ */
+ public static function runTransaction()
+ {
+ $args = func_get_args();
+ $cb = array_shift($args);
+ return self::runTransactionV($cb, $args);
+ }
+