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 ( 37c8f8...0cd075 )
by Andreas
04:18 queued 01:29
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
        } 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 ms until next retry
117
                    usleep(100000);
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
            2003, // Can't connect to MySQL server
134
            2006, // MySQL server has gone away
135
            2013, // Lost connection to MySQL server during query
136
        ]);
137
    }
138
139
    /**
140
     * Close database connection.
141
     */
142 1
    public function disconnect()
143
    {
144 1
        $this->pdo = null;
145 1
    }
146
147
    /**
148
     * Check if database connection is open.
149
     *
150
     * @return bool
151
     */
152 14
    public function isConnected()
153
    {
154 14
        return ($this->pdo instanceof PDO);
155
    }
156
157
    /**
158
     * Returns the PDO handle.
159
     *
160
     * Can be used to gain access to any special PDO methods.
161
     *
162
     * @return PDO
163
     */
164 2
    public function getPdo()
165
    {
166 2
        return $this->pdo;
167
    }
168
169
    /**
170
     * Creates and executes a PDO statement.
171
     *
172
     * @param string $sql
173
     * @param array  $parameters
174
     * @return PDOStatement
175
     */
176 5
    protected function executeQuery($sql, array $parameters = [])
177
    {
178 5
        $this->connect();
179
180
        try {
181 5
            $pdoStatement = $this->pdo->prepare($sql);
182 4
            $pdoStatement->execute($this->prepareParameters($parameters));
183
184 4
            return $pdoStatement;
185 1
        } catch (PDOException $e) {
186 1
            throw new QueryException($e, $sql, $parameters);
187
        }
188
    }
189
190
    /**
191
     * Execute an SQL statement and return the number of affected rows.
192
     *
193
     * @param string $sql
194
     * @param array  $parameters
195
     * @return int The number of rows affected
196
     */
197 2
    public function exec($sql, array $parameters = [])
198
    {
199 2
        $statement = $this->executeQuery($sql, $parameters);
200
201 1
        return $statement->rowCount();
202
    }
203
204
    /**
205
     * Execute an SQL statement and return the first row.
206
     *
207
     * @param string $sql
208
     * @param array  $parameters
209
     * @param bool   $indexedKeys
210
     * @return array|false
211
     */
212 1
    public function fetchRow($sql, array $parameters = [], $indexedKeys = false)
213
    {
214 1
        $statement = $this->executeQuery($sql, $parameters);
215
216 1
        return $statement->fetch($indexedKeys ? PDO::FETCH_NUM : PDO::FETCH_ASSOC);
217
    }
218
219
    /**
220
     * Execute an SQL statement and return all rows as an array.
221
     *
222
     * @param string $sql
223
     * @param array  $parameters
224
     * @param bool   $indexedKeys
225
     * @return array
226
     */
227 1
    public function fetchAll($sql, array $parameters = [], $indexedKeys = false)
228
    {
229 1
        $statement = $this->executeQuery($sql, $parameters);
230
231 1
        return $statement->fetchAll($indexedKeys ? PDO::FETCH_NUM : PDO::FETCH_ASSOC);
232
    }
233
234
    /**
235
     * Execute an SQL statement and return the first column of the first row.
236
     *
237
     * @param string $sql
238
     * @param array  $parameters
239
     * @return string|false
240
     */
241 1
    public function fetchOne($sql, array $parameters = [])
242
    {
243 1
        $statement = $this->executeQuery($sql, $parameters);
244
245 1
        return $statement->fetchColumn(0);
246
    }
247
248
    /**
249
     * Quote a value for a safe use in query (eg. bla'bla -> 'bla''bla').
250
     *
251
     * @param mixed $value
252
     * @return string
253
     */
254 1
    public function quote($value)
255
    {
256 1
        $this->connect();
257
258 1
        return $this->pdo->quote($value);
259
    }
260
261
    /**
262
     * Get id of the last inserted row.
263
     *
264
     * @return int
265
     */
266 1
    public function getLastInsertId()
267
    {
268 1
        $this->connect();
269
270 1
        return (int) $this->pdo->lastInsertId();
271
    }
272
273
    /**
274
     * Prepare parameters for database use.
275
     *
276
     * @param array $parameters
277
     * @return array
278
     */
279 4
    protected function prepareParameters(array $parameters = [])
280
    {
281 4
        foreach ($parameters as &$parameterValue) {
282 4
            if (is_bool($parameterValue)) {
283 4
                $parameterValue = (int) $parameterValue;
284
            }
285
        }
286 4
        unset($parameterValue);
287
288 4
        return $parameters;
289
    }
290
291
    /**
292
     * Begin transaction (turns off autocommit mode).
293
     *
294
     * @param bool $onlyIfNoActiveTransaction
295
     * @return bool
296
     */
297 4
    public function beginTransaction($onlyIfNoActiveTransaction = false)
298
    {
299 4
        $this->connect();
300
301 4
        if ($onlyIfNoActiveTransaction && $this->hasActiveTransaction()) {
302 1
            return false;
303
        }
304
305 4
        $this->pdo->beginTransaction();
306 4
        $this->hasActiveTransaction = true;
307
308 4
        return true;
309
    }
310
311
    /**
312
     * Commits current active transaction (restores autocommit mode).
313
     */
314 2
    public function commit()
315
    {
316 2
        $this->connect();
317
318 2
        $this->pdo->commit();
319 2
        $this->hasActiveTransaction = false;
320 2
    }
321
322
    /**
323
     * Rolls back current active transaction (restores autocommit mode).
324
     */
325 2
    public function rollBack()
326
    {
327 2
        $this->connect();
328
329 2
        $this->pdo->rollBack();
330 2
        $this->hasActiveTransaction = false;
331 2
    }
332
333
    /**
334
     * @return bool
335
     */
336 3
    public function hasActiveTransaction()
337
    {
338 3
        return $this->hasActiveTransaction;
339
    }
340
341
    /**
342
     * @param string $table
343
     * @param array $data
344
     * @return int The number of rows affected
345
     */
346 1
    public function insert($table, array $data)
347
    {
348 1
        $fields = array_keys($data);
349 1
        $valuePlaceholders = implode(', ', array_fill(0, count($fields), '?'));
350
351 1
        $sql = 'INSERT INTO `' . $table . '` '
352 1
            . ($fields ? '(`' . implode('`, `', $fields) . '`)' : '') . "\n"
353 1
            . ($fields ? 'VALUES (' . $valuePlaceholders . ')' : 'VALUES ()')
354
        ;
355
356 1
        return $this->exec($sql, array_values($data));
357
    }
358
359
    /**
360
     * @param string $table
361
     * @param array  $data
362
     * @param string $whereSql
363
     * @param array  $whereParameters
364
     * @return int The number of rows affected
365
     */
366 1
    public function update($table, array $data, $whereSql = '', array $whereParameters = [])
367
    {
368 1
        $setStrings = [];
369 1
        foreach (array_keys($data) as $field) {
370 1
            $setStrings[] = '`' . $field . '` = ?';
371
        }
372
373 1
        $sql = 'UPDATE `' . $table . "`\n"
374 1
            . 'SET ' . implode(', ', $setStrings)
375 1
            . ($whereSql ? "\nWHERE " . $whereSql : '')
376
        ;
377
378 1
        $parameters = array_merge(array_values($data), $whereParameters);
379
380 1
        return $this->exec($sql, $parameters);
381
    }
382
}
383