GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 2229bb...ca9a9a )
by Andreas
03:32
created

Db::exec()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 * Starlit Db.
4
 *
5
 * @copyright Copyright (c) 2016 Starweb / Ehandelslogik i Lund AB
6
 * @license   BSD 3-Clause
7
 */
8
9
namespace Starlit\Db;
10
11
use Starlit\Db\Exception\ConnectionException;
12
use Starlit\Db\Exception\QueryException;
13
use \PDO;
14
use \PDOException;
15
use \PDOStatement;
16
17
/**
18
 * Extended PDO database wrapper.
19
 *
20
 * @author Andreas Nilsson <http://github.com/jandreasn>
21
 */
22
class Db
23
{
24
    /**
25
     * Database handle/connection.
26
     *
27
     * @var PDO
28
     */
29
    protected $pdo;
30
31
    /**
32
     * @var string
33
     */
34
    protected $dsn;
35
36
    /**
37
     * @var string
38
     */
39
    protected $username;
40
41
    /**
42
     * @var string
43
     */
44
    protected $password;
45
46
    /**
47
     * @var array
48
     */
49
    protected $options;
50
51
    /**
52
     * @var bool
53
     */
54
    protected $hasActiveTransaction = false;
55
56
    /**
57
     * Constructor.
58
     *
59
     * @param string|PDO  $hostDsnOrPdo A MySQL host, a dsn or an existing PDO instance.
60
     * @param string|null $username
61
     * @param string|null $password
62
     * @param string|null $database
63
     * @param array       $options
64
     */
65 18
    public function __construct(
66
        $hostDsnOrPdo,
67
        $username = null,
68
        $password = null,
69
        $database = null,
70
        array $options = []
71
    ) {
72 18
        if ($hostDsnOrPdo instanceof PDO) {
73 18
            $this->pdo = $hostDsnOrPdo;
74 18
        } elseif (strpos($hostDsnOrPdo, ':') !== false) {
75
            $this->dsn = $hostDsnOrPdo;
76
        } else {
77
            $this->dsn = "mysql:host={$hostDsnOrPdo}" . ($database ? ";dbname={$database}" : '');
78
        }
79
80 18
        $this->username = $username;
81 18
        $this->password = $password;
82 18
        $this->options = $options;
83 18
    }
84
85
    /**
86
     */
87 13
    public function connect()
88
    {
89 13
        if ($this->isConnected()) {
90 13
            return;
91
        }
92
93
        $retries = isset($this->options['connectRetries'])? $this->options['connectRetries'] : 0;
94
        do {
95
            try {
96
                $defaultPdoOptions = [
97
                    PDO::ATTR_TIMEOUT            => 5,
98
                    // We want emulation by default (faster for single queries). Disable if you want to
99
                    // use proper native prepared statements
100
                    PDO::ATTR_EMULATE_PREPARES   => true,
101
                    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
102
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
103
                ];
104
                $pdoOptions = $defaultPdoOptions + (isset($this->options['pdo']) ? $this->options['pdo'] : []);
105
106
                $this->pdo = new PDO(
107
                    $this->dsn,
108
                    $this->username,
109
                    $this->password,
110
                    $pdoOptions
111
                );
112
113
                return;
114
            } catch (PDOException $e) {
115
                if ($this->isConnectionExceptionCausedByConnection($e) && $retries > 0) {
116
                    // Sleep for 100 - 500 ms until next retry
117
                    usleep(rand(100000, 500000));
118
                } else {
119
                    throw new ConnectionException($e);
120
                }
121
            }
122
123
        } while ($retries-- > 0);
124
    }
125
126
    /**
127
     * @param PDOException $exception
128
     * @return bool
129
     */
130
    private function isConnectionExceptionCausedByConnection(PDOException $exception)
131
    {
132
        return in_array($exception->getCode(), [
133
            2002, // Can't connect to MySQL server (Socket)
134
            2003, // Can't connect to MySQL server (TCP)
135
            2006, // MySQL server has gone away
136
            2013, // Lost connection to MySQL server during query
137
        ]);
138
    }
139
140
    /**
141
     * Close database connection.
142
     */
143 1
    public function disconnect()
144
    {
145 1
        $this->pdo = null;
146 1
    }
147
148
    /**
149
     * Check if database connection is open.
150
     *
151
     * @return bool
152
     */
153 14
    public function isConnected()
154
    {
155 14
        return ($this->pdo instanceof PDO);
156
    }
157
158
    /**
159
     * Returns the PDO handle.
160
     *
161
     * Can be used to gain access to any special PDO methods.
162
     *
163
     * @return PDO
164
     */
165 2
    public function getPdo()
166
    {
167 2
        return $this->pdo;
168
    }
169
170
    /**
171
     * Creates and executes a PDO statement.
172
     *
173
     * @param string $sql
174
     * @param array  $parameters
175
     * @return PDOStatement
176
     */
177 5
    protected function executeQuery($sql, array $parameters = [])
178
    {
179 5
        $this->connect();
180
181
        try {
182 5
            $pdoStatement = $this->pdo->prepare($sql);
183 4
            $pdoStatement->execute($this->prepareParameters($parameters));
184
185 4
            return $pdoStatement;
186 1
        } catch (PDOException $e) {
187 1
            throw new QueryException($e, $sql, $parameters);
188
        }
189
    }
190
191
    /**
192
     * Execute an SQL statement and return the number of affected rows.
193
     *
194
     * @param string $sql
195
     * @param array  $parameters
196
     * @return int The number of rows affected
197
     */
198 2
    public function exec($sql, array $parameters = [])
199
    {
200 2
        $statement = $this->executeQuery($sql, $parameters);
201
202 1
        return $statement->rowCount();
203
    }
204
205
    /**
206
     * Execute an SQL statement and return the first row.
207
     *
208
     * @param string $sql
209
     * @param array  $parameters
210
     * @param bool   $indexedKeys
211
     * @return array|false
212
     */
213 1
    public function fetchRow($sql, array $parameters = [], $indexedKeys = false)
214
    {
215 1
        $statement = $this->executeQuery($sql, $parameters);
216
217 1
        return $statement->fetch($indexedKeys ? PDO::FETCH_NUM : PDO::FETCH_ASSOC);
218
    }
219
220
    /**
221
     * Execute an SQL statement and return all rows as an array.
222
     *
223
     * @param string $sql
224
     * @param array  $parameters
225
     * @param bool   $indexedKeys
226
     * @return array
227
     */
228 1
    public function fetchAll($sql, array $parameters = [], $indexedKeys = false)
229
    {
230 1
        $statement = $this->executeQuery($sql, $parameters);
231
232 1
        return $statement->fetchAll($indexedKeys ? PDO::FETCH_NUM : PDO::FETCH_ASSOC);
233
    }
234
235
    /**
236
     * Execute an SQL statement and return the first column of the first row.
237
     *
238
     * @param string $sql
239
     * @param array  $parameters
240
     * @return string|false
241
     */
242 1
    public function fetchOne($sql, array $parameters = [])
243
    {
244 1
        $statement = $this->executeQuery($sql, $parameters);
245
246 1
        return $statement->fetchColumn(0);
247
    }
248
249
    /**
250
     * Quote a value for a safe use in query (eg. bla'bla -> 'bla''bla').
251
     *
252
     * @param mixed $value
253
     * @return string
254
     */
255 1
    public function quote($value)
256
    {
257 1
        $this->connect();
258
259 1
        return $this->pdo->quote($value);
260
    }
261
262
    /**
263
     * Get id of the last inserted row.
264
     *
265
     * @return int
266
     */
267 1
    public function getLastInsertId()
268
    {
269 1
        $this->connect();
270
271 1
        return (int) $this->pdo->lastInsertId();
272
    }
273
274
    /**
275
     * Prepare parameters for database use.
276
     *
277
     * @param array $parameters
278
     * @return array
279
     */
280 4
    protected function prepareParameters(array $parameters = [])
281
    {
282 4
        foreach ($parameters as &$parameterValue) {
283 4
            if (is_bool($parameterValue)) {
284 1
                $parameterValue = (int) $parameterValue;
285 1
            }
286 4
        }
287 4
        unset($parameterValue);
288
289 4
        return $parameters;
290
    }
291
292
    /**
293
     * Begin transaction (turns off autocommit mode).
294
     *
295
     * @param bool $onlyIfNoActiveTransaction
296
     * @return bool
297
     */
298 4
    public function beginTransaction($onlyIfNoActiveTransaction = false)
299
    {
300 4
        $this->connect();
301
302 4
        if ($onlyIfNoActiveTransaction && $this->hasActiveTransaction()) {
303 1
            return false;
304
        }
305
306 4
        $this->pdo->beginTransaction();
307 4
        $this->hasActiveTransaction = true;
308
309 4
        return true;
310
    }
311
312
    /**
313
     * Commits current active transaction (restores autocommit mode).
314
     */
315 2
    public function commit()
316
    {
317 2
        $this->connect();
318
319 2
        $this->pdo->commit();
320 2
        $this->hasActiveTransaction = false;
321 2
    }
322
323
    /**
324
     * Rolls back current active transaction (restores autocommit mode).
325
     */
326 2
    public function rollBack()
327
    {
328 2
        $this->connect();
329
330 2
        $this->pdo->rollBack();
331 2
        $this->hasActiveTransaction = false;
332 2
    }
333
334
    /**
335
     * @return bool
336
     */
337 3
    public function hasActiveTransaction()
338
    {
339 3
        return $this->hasActiveTransaction;
340
    }
341
342
    /**
343
     * @param string $table
344
     * @param array $data
345
     * @return int The number of rows affected
346
     */
347 1
    public function insert($table, array $data)
348
    {
349 1
        $fields = array_keys($data);
350 1
        $valuePlaceholders = implode(', ', array_fill(0, count($fields), '?'));
351
352 1
        $sql = 'INSERT INTO `' . $table . '` '
353 1
            . ($fields ? '(`' . implode('`, `', $fields) . '`)' : '') . "\n"
354 1
            . ($fields ? 'VALUES (' . $valuePlaceholders . ')' : 'VALUES ()')
355 1
        ;
356
357 1
        return $this->exec($sql, array_values($data));
358
    }
359
360
    /**
361
     * @param string $table
362
     * @param array  $data
363
     * @param string $whereSql
364
     * @param array  $whereParameters
365
     * @return int The number of rows affected
366
     */
367 1
    public function update($table, array $data, $whereSql = '', array $whereParameters = [])
368
    {
369 1
        $setStrings = [];
370 1
        foreach (array_keys($data) as $field) {
371 1
            $setStrings[] = '`' . $field . '` = ?';
372 1
        }
373
374 1
        $sql = 'UPDATE `' . $table . "`\n"
375 1
            . 'SET ' . implode(', ', $setStrings)
376 1
            . ($whereSql ? "\nWHERE " . $whereSql : '')
377 1
        ;
378
379 1
        $parameters = array_merge(array_values($data), $whereParameters);
380
381 1
        return $this->exec($sql, $parameters);
382
    }
383
}
384