Passed
Push — dependabot/github_actions/depe... ( d1016c )
by
unknown
11:16
created

ManagesTransactions::rollBack()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 25
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 6.2017

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
c 1
b 0
f 0
dl 0
loc 25
ccs 7
cts 11
cp 0.6364
rs 9.6111
cc 5
nc 6
nop 1
crap 6.2017
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Concerns;
4
5
use Closure;
6
use Throwable;
7
8
trait ManagesTransactions
9
{
10
    /**
11
     * Execute a Closure within a transaction.
12
     *
13
     * @param  Closure  $callback
14
     * @param  int  $attempts
15
     * @param  array  $collections
16
     * @return mixed
17
     *
18
     * @throws Throwable
19
     */
20 1
    public function transaction(Closure $callback, $attempts = 1, $collections = [])
21
    {
22 1
        for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
23 1
            $this->beginTransaction($collections);
24
25
            // We'll simply execute the given callback within a try / catch block and if we
26
            // catch any exception we can rollback this transaction so that none of this
27
            // gets actually persisted to a database or stored in a permanent fashion.
28
            try {
29 1
                $callbackResult = $callback($this);
30
            } catch (Throwable $e) {
31
                // If we catch an exception we'll rollback this transaction and try again if we
32
                // are not out of attempts. If we are out of attempts we will just throw the
33
                // exception back out and let the developer handle an uncaught exceptions.
34
35
                $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

35
                $this->/** @scrutinizer ignore-call */ 
36
                       handleTransactionException(
Loading history...
36
                    $e,
37
                    $currentAttempt,
38
                    $attempts
39
                );
40
41
                continue;
42
            }
43
44
            try {
45 1
                if ($this->transactions == 1) {
46 1
                    $this->commit();
47
                }
48
49 1
                $this->transactions = max(0, $this->transactions - 1);
0 ignored issues
show
Bug Best Practice introduced by
The property transactions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
50
            } catch (Throwable $e) {
51
                $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

51
                $this->/** @scrutinizer ignore-call */ 
52
                       handleCommitTransactionException(
Loading history...
52
                    $e,
53
                    $currentAttempt,
54
                    $attempts
55
                );
56
57
                continue;
58
            }
59
60 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

60
            $this->/** @scrutinizer ignore-call */ 
61
                   fireConnectionEvent('committed');
Loading history...
61
62 1
            return $callbackResult;
63
        }
64
    }
65
66
    /**
67
     * Start a new database transaction.
68
     *
69
     * @param  array<string, array<string>>  $collections
70
     *
71
     * @throws Throwable
72
     */
73 169
    public function beginTransaction(array $collections = []): void
74
    {
75 169
        $this->createTransaction($collections);
76
77 169
        $this->transactions++;
78
79 169
        $this->fireConnectionEvent('beganTransaction');
80
    }
81
82
    /**
83
     * Create a transaction within the database.
84
     *
85
     * @param  array<string, array<string>>  $collections
86
     *
87
     * @throws Throwable
88
     */
89 169
    protected function createTransaction(array $collections = []): void
90
    {
91 169
        if ($this->transactions == 0) {
92 169
            $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

92
            $this->/** @scrutinizer ignore-call */ 
93
                   reconnectIfMissingConnection();
Loading history...
93
94
            try {
95 169
                $this->arangoClient->begin($collections);
96
            } catch (Throwable $e) {
97
                $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

97
                $this->/** @scrutinizer ignore-call */ 
98
                       handleBeginTransactionException($e);
Loading history...
98
            }
99
        }
100
    }
101
102
    /**
103
     * Commit the active database transaction.
104
     *
105
     * @return void
106
     *
107
     * @throws Throwable
108
     */
109 3
    public function commit()
110
    {
111 3
        if ($this->transactions == 1) {
112 3
            $this->arangoClient->commit();
113
        }
114
115 3
        $this->transactions = max(0, $this->transactions - 1);
0 ignored issues
show
Bug Best Practice introduced by
The property transactions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
116
117 3
        $this->fireConnectionEvent('committed');
118
    }
119
120
    /**
121
     * Rollback the active database transaction.
122
     *
123
     * @param  int|null  $toLevel
124
     * @return void
125
     *
126
     * @throws \Throwable
127
     */
128 166
    public function rollBack($toLevel = null)
129
    {
130
        // We allow developers to rollback to a certain transaction level. We will verify
131
        // that this given transaction level is valid before attempting to rollback to
132
        // that level. If it's not we will just return out and not attempt anything.
133 166
        $toLevel = is_null($toLevel)
134 166
            ? $this->transactions - 1
135
            : $toLevel;
136
137 166
        if ($toLevel < 0 || $toLevel >= $this->transactions) {
138
            return;
139
        }
140
141
        // Next, we will actually perform this rollback within this database and fire the
142
        // rollback event. We will also set the current transaction level to the given
143
        // level that was passed into this method so it will be right from here out.
144
        try {
145 166
            $this->performRollBack($toLevel);
146
        } catch (Throwable $e) {
147
            $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

147
            $this->/** @scrutinizer ignore-call */ 
148
                   handleRollBackException($e);
Loading history...
148
        }
149
150 166
        $this->transactions = $toLevel;
0 ignored issues
show
Bug Best Practice introduced by
The property transactions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
151
152 166
        $this->fireConnectionEvent('rollingBack');
153
    }
154
155
    /**
156
     * Perform a rollback within the database.
157
     *
158
     * @param  int  $toLevel
159
     * @return void
160
     *
161
     * @throws Throwable
162
     */
163 166
    protected function performRollBack($toLevel)
164
    {
165 166
        if ($toLevel == 0) {
166 166
            $this->arangoClient->abort();
167
        }
168
    }
169
}
170