DatabaseDriver   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 360
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 43
dl 0
loc 360
rs 10
c 2
b 0
f 0
wmc 24

14 Methods

Rating   Name   Duplication   Size   Complexity  
A hasError() 0 3 1
A errorMessage() 0 3 2
A escape() 0 4 1
A prepareAndExecuteSql() 0 13 2
A cleanError() 0 3 1
A getConnection() 0 3 1
A getDriverName() 0 3 1
B __construct() 0 22 7
A errorCode() 0 3 2
A getHostName() 0 3 1
A closeConnection() 0 3 1
A defaultOutputFormat() 0 3 1
A escapeList() 0 7 2
A sqlCreateTableOptions() 0 3 1
1
<?php declare(strict_types=1);
2
3
/** 
4
 *  ___      _        _
5
 * | _ \__ _| |_ __ _| |__  __ _ ___ ___
6
 * |  _/ _` |  _/ _` | '_ \/ _` (_-</ -_)
7
 * |_| \__,_|\__\__,_|_.__/\__,_/__/\___|
8
 * 
9
 * This file is part of Kristuff\Patabase.
10
 * (c) Kristuff <[email protected]>
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 *
15
 * @version    1.0.1
16
 * @copyright  2017-2022 Christophe Buliard
17
 */
18
19
namespace Kristuff\Patabase\Driver;
20
21
use Kristuff\Patabase\Exception;
22
use Kristuff\Patabase\Output;
23
use PDO;
24
25
/**
26
 *  Class DatabaseDriver
27
 *
28
 *  Base class for Database(only) drivers
29
 */
30
abstract class DatabaseDriver
31
{
32
    /**
33
     * PDO connection
34
     *
35
     * @access protected
36
     * @var \PDO
37
     */
38
    protected $pdo = null;
39
40
    /**
41
     * List of DSN attributes
42
     * The Data Source Name, or DSN, contains the information required 
43
     * to connect to the database. 
44
     *
45
     * @access protected
46
     * @var array
47
     */
48
    protected $dsnAttributes = array();
49
50
    /**
51
     * Error
52
     *
53
     * @access protected
54
     * @var    array
55
     */
56
    protected $error = array();
57
58
    /**
59
     * The default output format
60
     *
61
     * @access private
62
     * @var    string
63
     */
64
    private $defaultOutputFormat = Output::ASSOC;
65
66
    /**
67
     * the current hostname
68
     *
69
     * @Var string 
70
     */
71
    private $hostname;
72
73
    /**
74
     * the current driver
75
     *
76
     * @Var string 
77
     */
78
    private $driverName;
79
80
    /**
81
     * Options for CREATE TABLE 
82
     *
83
     * @access protected
84
     * @var string
85
     */
86
    public function sqlCreateTableOptions(): string
87
    {
88
        return '';    
89
    } 
90
91
    /**
92
     * Gets/returns the default output format 
93
     *
94
     * @access public
95
     * @return string
96
     */
97
    public function defaultOutputFormat(): string
98
    {
99
        return $this->defaultOutputFormat;
100
    }
101
102
    /**
103
     * Get the current hostname
104
     *
105
     * @access public
106
     * @return string
107
     */
108
    public function getHostName(): string
109
    {
110
        return $this->hostname;    
111
    }
112
113
    /**
114
     * Get the current driver name
115
     *
116
     * @access public
117
     * @return string
118
     */
119
    public function getDriverName(): string
120
    {
121
        return $this->driverName;    
122
    }
123
124
    /**
125
     * Escape a given string with driver escape chars
126
     * 
127
     * @access public
128
     * @param string   $str  The value to escape
129
     *
130
     * @return string
131
     */
132
    public function escape(string $str): string
133
    {
134
       $list = explode('.', $str);
135
       return implode('.', $this->escapeList($list));
136
    }
137
138
    /**
139
     * Escape an array of string with driver escape chars
140
     *
141
     * @access public
142
     * @param array    $values  The array of values
143
     *
144
     * @return array
145
     */
146
    public function escapeList(array $values): array
147
    {
148
        $newList = array();
149
        foreach ($values as $identifier) {
150
            $newList[] = $this->escapeIdentifier($identifier);
151
        }
152
        return $newList;
153
    }
154
155
    /**
156
     * Constructor
157
     *
158
     * @access public
159
     * @param array    $settings               The connection settings
160
     */
161
    public function __construct(array $settings)
162
    {
163
        // check for required attributes
164
        foreach ($this->dsnAttributes as $attribute) {
165
            if (! array_key_exists($attribute, $settings)) {
166
                throw new Exception\MissingArgException('This configuration parameter is missing: "'.$attribute.'"');
167
            }
168
        }
169
170
        // defaut output format
171
        if (array_key_exists('default_output_format', $settings)){
172
            $format = $settings['default_output_format'];
173
            if (!in_array($format, $this->outputFormats)){
0 ignored issues
show
Bug Best Practice introduced by
The property outputFormats does not exist on Kristuff\Patabase\Driver\DatabaseDriver. Did you maybe forget to declare it?
Loading history...
174
                throw new Exception\InvalidArgException('The default output format specified is invalid.');
175
            } 
176
            $this->defaultOutputFormat = $format;
177
        }
178
179
        $this->createConnection($settings);
180
        $this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
181
        $this->hostname = array_key_exists('hostname',$settings) && $settings['hostname'] ? $settings['hostname'] : '';
182
        $this->driverName = $settings['driver'];
183
    }
184
185
    /**
186
     * Has error
187
     *
188
     * @access public
189
     * @return bool     True if the query has genaretd an error
190
     */
191
    public function hasError(): bool
192
    {
193
        return !empty($this->error);
194
    }
195
196
    /**
197
     * Reset error
198
     *
199
     * @access public
200
     * @return void
201
     */
202
    public function cleanError(): void
203
    {
204
        $this->error = array();
205
    }
206
207
    /**
208
     * Error Code
209
     *
210
     * @access public
211
     * @return int
212
     */
213
    public function errorCode(): int
214
    {
215
        return !empty($this->error) ? $this->error['code']: '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! empty($this->er...his->error['code'] : '' could return the type string which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
216
    }
217
218
    /**
219
     * Error Message
220
     *
221
     * @access public
222
     * @return bool     True if the query has genaretd an error
223
     */
224
    public function errorMessage(): string
225
    {
226
        return !empty($this->error) ? $this->error['message'] : '';
0 ignored issues
show
Bug Best Practice introduced by
The expression return ! empty($this->er...->error['message'] : '' also could return the type string which is incompatible with the documented return type boolean.
Loading history...
227
    }
228
229
    /**
230
     * Get the PDO connection
231
     *
232
     * @access public
233
     * @return PDO
234
     */
235
    public function getConnection(): PDO
236
    {
237
        return $this->pdo;
238
    }
239
    
240
    /**
241
     * Prepare and execute a query 
242
     *
243
     * @access public
244
     * @param string   $sql            The SQL query
245
     * @param array    $parameters     The SQL parameters
246
     *
247
     * @return bool     true if the query is executed with success, otherwise false
248
     */
249
    public function prepareAndExecuteSql(string $sql, array $parameters = []): bool
250
    {
251
        // clear the current errors
252
        $this->cleanError();
253
        try {
254
            // prepare and execute
255
            $pdoStatement = $this->pdo->prepare($sql);
256
            return $pdoStatement->execute($parameters);
257
        } catch (\PDOException $e) {
258
            // register error
259
            $this->error['code'] = (int)$e->getCode();
260
            $this->error['message'] = $e->getMessage();
261
            return false;
262
        }
263
    }    
264
265
    /**
266
     * Release the PDO connection
267
     *
268
     * @access public
269
     * @return void
270
     */
271
    public function closeConnection(): void
272
    {
273
        $this->pdo = null;
274
    }
275
276
    /**
277
     * Create a PDO connection from given settings
278
     *
279
     * @access public
280
     * @param array    $settings
281
     *
282
     * @return void
283
     */
284
    abstract protected function createConnection(array $settings): void;
285
286
    /**
287
     * Escape identifier
288
     *
289
     * @access public
290
     * @param string   $identifier
291
     *
292
     * @return string
293
     */
294
    abstract public function escapeIdentifier(string $identifier): string;
295
296
    /**
297
     * Escape value
298
     *
299
     * @access public
300
     * @param string   $value
301
     *
302
     * @return string
303
     */
304
    abstract public function escapeValue(string $value) : string;
305
   
306
    /**
307
     * Get last inserted id
308
     *
309
     * @access public
310
     * @return string
311
     */
312
    abstract public function lastInsertedId(): string;
313
314
    /**
315
     * Enable foreign keys
316
     *
317
     * @access public
318
     * @return void
319
     */
320
    abstract public function enableForeignKeys(): void;
321
322
    /**
323
     * Disable foreign keys
324
     *
325
     * @access public
326
     * @return void
327
     */
328
    abstract public function disableForeignKeys(): void;
329
330
    /**
331
     * Get whether foreign keys are enabled or not
332
     * 
333
     * @access public
334
     * @return bool     true if foreign keys are enabled, otherwise false
335
     */
336
    abstract function isForeignKeyEnabled() : bool;
337
338
    /**
339
     * Add a foreign key
340
     * 
341
     * @access public
342
     * @param string   $fkName         The constraint name
343
     * @param string   $srcTable       The source table
344
     * @param string   $srcColumn      The source column 
345
     * @param string   $refTable       The referenced table
346
     * @param string   $refColumn      The referenced column
347
     *
348
     * @return bool    True if the foreign key has been created, otherwise false
349
     */
350
    abstract public function addForeignKey(string $fkName, string $srcTable, string $srcColumn, string $refTable, string $refColumn) : bool;
351
352
    /**
353
     * Drop a foreign key
354
     * 
355
     * @access public
356
     * @param string   $fkName         The constraint name
357
     * @param string   $tableName      The source table
358
     *
359
     * @return bool    True if the foreign key has been dropped, otherwise false
360
     */
361
    abstract public function dropForeignKey(string $fkName, string $tableName): bool;
362
363
    /**
364
     * Get the SQL for show tables
365
     *
366
     * @access public
367
     * @return string
368
     */
369
    abstract public function sqlShowTables(): string;
370
371
    /**
372
     * Get the SQL for RANDOM function
373
     *
374
     * @access public
375
     * @param  mixed   $seed   The seed for random function
376
     *
377
     * @return string
378
     */
379
    abstract public function sqlRandom(): string;
380
381
    /**
382
     * Get the SQL for auto increment column
383
     *
384
     * @access public
385
     * @param string   $type   The sql column type
386
     *
387
     * @return string
388
     */
389
    abstract public function sqlColumnAutoIncrement(string $type): string;
390
}