LogicalConnection   B
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 291
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 88.17%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 36
c 1
b 0
f 0
lcom 1
cbo 4
dl 0
loc 291
ccs 82
cts 93
cp 0.8817
rs 8.8

21 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
A getName() 0 4 1
A getDsn() 0 4 1
A getManager() 0 4 1
A beginTransaction() 0 4 1
A commit() 0 4 1
A rollBack() 0 12 2
A transactional() 0 11 2
A getTransactionNestingLevel() 0 4 1
A executeUpdate() 0 4 1
A executeQuery() 0 4 1
A insert() 0 13 2
A lastInsertId() 0 4 1
A reconnectIfNeeded() 0 16 3
A connect() 0 4 1
A getWrappedConnection() 0 4 1
A ping() 0 12 2
A isEmbeddedDatabase() 0 9 2
A createTable() 0 4 1
B getConnection() 0 20 6
A getDummySelectSQL() 0 15 3
1
<?php
2
namespace PSB\Persistence\Doctrine1;
3
4
5
use PSB\Core\Exception\CriticalErrorException;
6
use PSB\Core\Util\Guard;
7
8
class LogicalConnection
9
{
10
    /**
11
     * @var string
12
     */
13
    private $name;
14
15
    /**
16
     * @var string
17
     */
18
    private $dsn;
19
20
    /**
21
     * @var \Doctrine_Manager
22
     */
23
    private $manager;
24
25
    /**
26
     * @param string            $name
27
     * @param string            $dsn
28
     * @param \Doctrine_Manager $manager
29
     */
30 5
    public function __construct($name = null, $dsn, \Doctrine_Manager $manager)
31
    {
32 5
        Guard::againstNullAndEmpty('dns', $dsn);
33
34 4
        $this->name = $name === '' ? null : $name;
35 4
        $this->dsn = $dsn;
36 4
        $this->manager = $manager;
37 4
    }
38
39
    /**
40
     * @return string
41
     */
42 3
    public function getName()
43
    {
44 3
        return $this->name;
45
    }
46
47
    /**
48
     * @return string
49
     */
50 3
    public function getDsn()
51
    {
52 3
        return $this->dsn;
53
    }
54
55
    /**
56
     * @return \Doctrine_Manager
57
     */
58 3
    public function getManager()
59
    {
60 3
        return $this->manager;
61
    }
62
63
    /**
64
     * @return int
65
     */
66 10
    public function beginTransaction()
67
    {
68 10
        return $this->getConnection()->beginTransaction();
69
    }
70
71
    /**
72
     * @return bool
73
     */
74 7
    public function commit()
75
    {
76 7
        return $this->getConnection()->commit();
77
    }
78
79
    /**
80
     * Rolls back the transaction.
81
     * It makes sure that the connection is in the correct state regardless of what happened before.
82
     * Correct state means that the connection does not have a transaction nesting level > 0
83
     *
84
     * @return bool
85
     */
86 6
    public function rollBack()
87
    {
88
        /**
89
         * Roll back all the way as this is supposed to be the top level transaction and we want to reset
90
         * the nesting level
91
         */
92 6
        $transactionNestingLevel = $this->getConnection()->getTransactionLevel();
93 6
        for ($i = 0; $i < $transactionNestingLevel - 1; $i++) {
94 1
            $this->getConnection()->rollBack();
95 1
        }
96 6
        return $this->getConnection()->rollBack();
97
    }
98
99
    /**
100
     * @param \Closure $func
101
     *
102
     * @throws \Exception
103
     */
104 7
    public function transactional(\Closure $func)
105
    {
106 7
        $this->beginTransaction();
107
        try {
108 7
            $func($this);
109 7
            $this->commit();
110 7
        } catch (\Exception $e) {
111 1
            $this->rollback();
112 1
            throw $e;
113
        }
114 7
    }
115
116
    /**
117
     * @return int
118
     */
119 2
    public function getTransactionNestingLevel()
120
    {
121 2
        return $this->getConnection()->getTransactionLevel();
122
    }
123
124
    /**
125
     * @param string $query
126
     * @param array  $params
127
     *
128
     * @return \Doctrine_Adapter_Statement|\PDOStatement
129
     */
130 4
    public function executeUpdate($query, array $params = [])
131
    {
132 4
        return $this->getConnection()->standaloneQuery($query, $params);
133
    }
134
135
    /**
136
     * @param string $query
137
     * @param array  $params
138
     *
139
     * @return \PDOStatement|\Doctrine_Adapter_Statement
140
     */
141 16
    public function executeQuery($query, array $params = [])
142
    {
143 16
        return $this->getConnection()->standaloneQuery($query, $params);
144
    }
145
146
    /**
147
     * @param string $tableName
148
     * @param array  $data
149
     *
150
     * @return int
151
     */
152 7
    public function insert($tableName, array $data)
153
    {
154 7
        $columns = array_keys($data);
155 7
        foreach ($columns as $key => $value) {
156 7
            $columns[$key] = $this->getConnection()->quoteIdentifier($value);
157 7
        }
158
159 7
        $query = 'INSERT INTO ' . $this->getConnection()->quoteIdentifier($tableName)
160 7
            . ' (' . implode(', ', $columns) . ')'
161 7
            . ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
162
163 7
        return $this->getConnection()->exec($query, array_values($data));
164
    }
165
166
    /**
167
     * @return string
168
     */
169 2
    public function lastInsertId()
170
    {
171 2
        return $this->getConnection()->lastInsertId();
172
    }
173
174
    /**
175
     * @param \Exception $e
176
     *
177
     * @return \Exception
178
     */
179 4
    public function reconnectIfNeeded(\Exception $e)
180
    {
181
        // presumably, any exception caught here is related to some connection error
182 4
        if (!$this->ping()) {
183
            // if pinging fails, we try to reconnect
184
            try {
185 4
                $this->manager->closeConnection($this->getConnection());
186 4
                $this->getConnection()->connect();
187 4
            } catch (\Exception $e) {
188
                // if reconnecting fails, there is no way that the bus can continue to function
189
                return new CriticalErrorException("Database connection failed.", 0, $e);
190
            }
191 4
        }
192
193 4
        return $e;
194
    }
195
196
    /**
197
     * @return bool
198
     * @throws \Doctrine_Connection_Exception
199
     */
200 6
    public function connect()
201
    {
202 6
        return $this->getConnection()->connect();
203
    }
204
205
    /**
206
     * @return \Doctrine_Connection
207
     */
208 5
    public function getWrappedConnection()
209
    {
210 5
        return $this->getConnection();
211
    }
212
213
    /**
214
     * @return bool
215
     */
216 4
    public function ping()
217
    {
218 4
        $this->connect();
219
220
        try {
221 4
            $this->executeQuery($this->getDummySelectSQL());
222 4
        } catch (\Exception $e) {
223 4
            return false;
224
        }
225
226 4
        return true;
227
    }
228
229
    /**
230
     * @return bool
231
     */
232 4
    public function isEmbeddedDatabase()
233
    {
234 4
        $driverName = $this->getConnection()->getDriverName();
235 4
        if (stripos($driverName, 'sqlite') !== false) {
236
            return true;
237
        }
238
239 4
        return false;
240
    }
241
242
    /**
243
     * @param string $tableName
244
     * @param array  $fields
245
     * @param array  $options
246
     */
247
    public function createTable($tableName, array $fields = [], array $options = [])
248
    {
249
        $this->getConnection()->export->createTable($tableName, $fields, $options);
250
    }
251
252
    /**
253
     * @return \Doctrine_Connection
254
     * @throws \Doctrine_Connection_Exception
255
     * @throws \Doctrine_Manager_Exception
256
     */
257 16
    private function getConnection()
258
    {
259
        // if there is a name and a connection with that name exists, use that one
260 16
        if ($this->name && $this->manager->contains($this->name)) {
261
            return $this->manager->getConnection($this->name);
262
        }
263
264
        // if there is a name and no connection with that name exists, create one
265 16
        if ($this->name) {
266
            return $this->manager->openConnection($this->dsn, $this->name);
0 ignored issues
show
Documentation introduced by
$this->dsn is of type string, but the function expects a object<PDO>|object<Doctrine_Adapter_Interface>.

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...
267
        }
268
269
        // if there is no name (so it's not using multiple connections) and one connection is present, use that one
270 16
        if (!$this->name && $this->manager->count()) {
271 16
            return $this->manager->getCurrentConnection();
272
        }
273
274
        // if there is no name (so it's not using multiple connections) and no connection is present, create one
275 4
        return $this->manager->openConnection($this->dsn);
0 ignored issues
show
Documentation introduced by
$this->dsn is of type string, but the function expects a object<PDO>|object<Doctrine_Adapter_Interface>.

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...
276
    }
277
278
    /**
279
     * Taken from doctrine 2
280
     *
281
     * @return string
282
     */
283 4
    private function getDummySelectSQL()
284
    {
285 4
        $driverName = strtolower($this->getConnection()->getDriverName());
286
        switch ($driverName) {
287 4
            case 'db2':
288
                $sql = 'SELECT 1 FROM sysibm.sysdummy1';
289
                break;
290 4
            case 'oci':
291
                $sql = 'SELECT 1 FROM dual';
292
                break;
293 4
            default:
294 4
                $sql = 'SELECT 1';
295 4
        }
296 4
        return $sql;
297
    }
298
}
299