Completed
Push — work-fleets ( 2bd11a...17dd3b )
by SuperNova.WS
06:36
created

DbTransaction::rollback()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 13
rs 9.4285
1
<?php
2
3
/**
4
 * Created by Gorlum 31.07.2016 12:08
5
 */
6
7
namespace DBAL;
8
9
use \classSupernova;
10
use \SnCache;
11
use \db_mysql;
12
13
class DbTransaction {
14
15
  protected $db_in_transaction = false;
16
  protected $transaction_id = 0;
17
18
  /**
19
   * @var db_mysql $db
20
   */
21
  protected $db;
22
23
  /**
24
   * DbTransaction constructor.
25
   *
26
   * @param db_mysql $db
27
   */
28
  public function __construct($db) {
29
    $this->db = $db;
30
  }
31
32
  /**
33
   * Эта функция проверяет статус транзакции
34
   *
35
   * Это - низкоуровневая функция. В нормальном состоянии движка её сообщения никогда не будут видны
36
   *
37
   * @param null|true|false $status Должна ли быть запущена транзакция в момент проверки
38
   *   <p>null - транзакция НЕ должна быть запущена</p>
39
   *   <p>true - транзакция должна быть запущена - для совместимости с $for_update</p>
40
   *   <p>false - всё равно - для совместимости с $for_update</p>
41
   *
42
   * @return bool Текущий статус транзакции
43
   */
44
  public function check($status = null) {
45
    $error_msg = false;
46
    if ($status && !$this->db_in_transaction) {
47
      $error_msg = 'No transaction started for current operation';
48
    } elseif ($status === null && $this->db_in_transaction) {
49
      $error_msg = 'Transaction is already started';
50
    }
51
52
    if (!empty($error_msg)) {
53
      // TODO - Убрать позже
54
      print('<h1>СООБЩИТЕ ЭТО АДМИНУ: sn_db_transaction_check() - ' . $error_msg . '</h1>');
55
      $backtrace = debug_backtrace();
56
      array_shift($backtrace);
57
      pdump($backtrace);
58
      die($error_msg);
59
    }
60
61
    return $this->db_in_transaction;
62
  }
63
64
  public function start($level = '') {
65
    $this->check(null);
66
67
    $level ? $this->db->doExecute('SET TRANSACTION ISOLATION LEVEL ' . $level) : false;
68
69
    $this->transaction_id++;
70
    $this->db->doExecute('START TRANSACTION');
71
72
    if (classSupernova::$gc->config->db_manual_lock_enabled) {
73
      classSupernova::$gc->config->db_loadItem('var_db_manually_locked');
0 ignored issues
show
Bug introduced by
The method db_loadItem does only exist in classConfig, but not in Closure.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
74
      classSupernova::$gc->config->db_saveItem('var_db_manually_locked', SN_TIME_SQL);
0 ignored issues
show
Bug introduced by
The method db_saveItem does only exist in classConfig, but not in Closure.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
75
    }
76
77
    $this->db_in_transaction = true;
78
    SnCache::locatorReset();
79
    SnCache::queriesReset();
80
81
    return $this->transaction_id;
82
  }
83
84
  // TODO - move changeset data and methods somewhere
85
  public function commit() {
86
    $this->check(true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a null|object<DBAL\true>|false.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
87
88
    if (!empty(classSupernova::$delayed_changset)) {
89
      classSupernova::db_changeset_apply(classSupernova::$delayed_changset, true);
90
    }
91
    $this->db->doExecute('COMMIT');
92
93
    return $this->db_transaction_clear();
94
  }
95
96
  public function rollback() {
97
    // TODO - вообще-то тут тоже надо проверять есть ли транзакция
98
99
    if (!empty(classSupernova::$delayed_changset)) {
100
      // TODO Для этапа 1 - достаточно чистить только те таблицы, что были затронуты
101
      // Для этапа 2 - чистить только записи
102
      // Для этапа 3 - возвращать всё
103
      SnCache::cache_clear_all(true);
104
    }
105
    $this->db->doExecute('ROLLBACK');
106
107
    return $this->db_transaction_clear();
108
  }
109
110
  protected function db_transaction_clear() {
111
    classSupernova::$delayed_changset = array();
112
    SnCache::cache_lock_unset_all();
113
114
    $this->db_in_transaction = false;
115
    $this->transaction_id++;
116
117
    return $this->transaction_id;
118
  }
119
120
  /**
121
   * Get Transaction ID for next query
122
   *
123
   * If transaction is in progress - next ID would be equal to current
124
   * Otherwise we should increase ID and return this value
125
   *
126
   * @return int
127
   */
128
  public function getNextQueryTransactionId() {
129
    return $this->check(false) ? $this->transaction_id : $this->transaction_id++;
130
  }
131
132
}
133