Passed
Branch next (97e380)
by Bas
03:07
created

ManagesTransactions::performRollBack()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Concerns;
4
5
use Closure;
6
use Throwable;
7
8
trait ManagesTransactions
9
{
10
    /**
11
     * @var int
12
     */
13
    protected $transactions = 0;
14
15
    /**
16
     * Execute a Closure within a transaction.
17
     *
18
     * @param  Closure  $callback
19
     * @param  int  $attempts
20
     * @param  array  $collections
21
     * @return mixed
22
     *
23
     * @throws Throwable
24
     */
25 1
    public function transaction(Closure $callback, $attempts = 1, $collections = [])
26
    {
27 1
        for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
28 1
            $this->beginTransaction($collections);
29
30
            // We'll simply execute the given callback within a try / catch block and if we
31
            // catch any exception we can rollback this transaction so that none of this
32
            // gets actually persisted to a database or stored in a permanent fashion.
33
            try {
34 1
                $callbackResult = $callback($this);
35
            } catch (Throwable $e) {
36
                // If we catch an exception we'll rollback this transaction and try again if we
37
                // are not out of attempts. If we are out of attempts we will just throw the
38
                // exception back out and let the developer handle an uncaught exceptions.
39
40
                $this->handleTransactionException(
0 ignored issues
show
Bug introduced by
It seems like handleTransactionException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

40
                $this->/** @scrutinizer ignore-call */ 
41
                       handleTransactionException(
Loading history...
41
                    $e,
42
                    $currentAttempt,
43
                    $attempts
44
                );
45
46
                continue;
47
            }
48
49
            try {
50 1
                if ($this->transactions == 1) {
51 1
                    $this->commit();
52
                }
53
54 1
                $this->transactions = max(0, $this->transactions - 1);
55
            } catch (Throwable $e) {
56
                $this->handleCommitTransactionException(
0 ignored issues
show
Bug introduced by
It seems like handleCommitTransactionException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

56
                $this->/** @scrutinizer ignore-call */ 
57
                       handleCommitTransactionException(
Loading history...
57
                    $e,
58
                    $currentAttempt,
59
                    $attempts
60
                );
61
62
                continue;
63
            }
64
65 1
            $this->fireConnectionEvent('committed');
0 ignored issues
show
Bug introduced by
It seems like fireConnectionEvent() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
            $this->/** @scrutinizer ignore-call */ 
66
                   fireConnectionEvent('committed');
Loading history...
66
67 1
            return $callbackResult;
68
        }
69
    }
70
71
    /**
72
     * Start a new database transaction.
73
     *
74
     * @param  array  $collections
75
     * @return void
76
     *
77
     * @throws Throwable
78
     */
79 5
    public function beginTransaction($collections = [])
80
    {
81 5
        $this->createTransaction($collections);
82
83 5
        $this->transactions++;
84
85 5
        $this->fireConnectionEvent('beganTransaction');
86 5
    }
87
88
    /**
89
     * Create a transaction within the database.
90
     *
91
     * @param  array  $collections
92
     * @return void
93
     *
94
     */
95 5
    protected function createTransaction($collections = [])
96
    {
97 5
        if ($this->transactions == 0) {
98 5
            $this->reconnectIfMissingConnection();
0 ignored issues
show
Bug introduced by
It seems like reconnectIfMissingConnection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

98
            $this->/** @scrutinizer ignore-call */ 
99
                   reconnectIfMissingConnection();
Loading history...
99
100
            try {
101 5
                $this->arangoClient->begin($collections);
102
            } catch (Throwable $e) {
103
                $this->handleBeginTransactionException($e);
0 ignored issues
show
Bug introduced by
It seems like handleBeginTransactionException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
                $this->/** @scrutinizer ignore-call */ 
104
                       handleBeginTransactionException($e);
Loading history...
104
            }
105
        }
106 5
    }
107
108
    /**
109
     * Commit the active database transaction.
110
     *
111
     * @return void
112
     *
113
     * @throws Throwable
114
     */
115 4
    public function commit()
116
    {
117 4
        if ($this->transactions == 1) {
118 3
            $this->arangoClient->commit();
119
        }
120
121 4
        $this->transactions = max(0, $this->transactions - 1);
122
123 4
        $this->fireConnectionEvent('committed');
124 4
    }
125
126
    /**
127
     * Rollback the active database transaction.
128
     *
129
     * @param  int|null  $toLevel
130
     * @return void
131
     *
132
     * @throws \Throwable
133
     */
134 1
    public function rollBack($toLevel = null)
135
    {
136
        // We allow developers to rollback to a certain transaction level. We will verify
137
        // that this given transaction level is valid before attempting to rollback to
138
        // that level. If it's not we will just return out and not attempt anything.
139 1
        $toLevel = is_null($toLevel)
140 1
            ? $this->transactions - 1
141 1
            : $toLevel;
142
143 1
        if ($toLevel < 0 || $toLevel >= $this->transactions) {
144
            return;
145
        }
146
147
        // Next, we will actually perform this rollback within this database and fire the
148
        // rollback event. We will also set the current transaction level to the given
149
        // level that was passed into this method so it will be right from here out.
150
        try {
151 1
            $this->performRollBack($toLevel);
152
        } catch (Throwable $e) {
153
            $this->handleRollBackException($e);
0 ignored issues
show
Bug introduced by
It seems like handleRollBackException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

153
            $this->/** @scrutinizer ignore-call */ 
154
                   handleRollBackException($e);
Loading history...
154
        }
155
156 1
        $this->transactions = $toLevel;
157
158 1
        $this->fireConnectionEvent('rollingBack');
159 1
    }
160
161
    /**
162
     * Perform a rollback within the database.
163
     *
164
     * @param  int  $toLevel
165
     * @return void
166
     *
167
     * @throws Throwable
168
     */
169 1
    protected function performRollBack($toLevel)
170
    {
171 1
        if ($toLevel == 0) {
172 1
            $this->arangoClient->abort();
173
        }
174 1
    }
175
}
176