Completed
Push — master ( 9e7cb4...919b07 )
by Arman
19s queued 16s
created

IdiormDbal::connect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.7
13
 */
14
15
namespace Quantum\Libraries\Database\Adapters\Idiorm;
16
17
use Quantum\Libraries\Database\Adapters\Idiorm\Statements\Criteria;
18
use Quantum\Libraries\Database\Adapters\Idiorm\Statements\Reducer;
19
use Quantum\Libraries\Database\Adapters\Idiorm\Statements\Result;
20
use Quantum\Libraries\Database\Adapters\Idiorm\Statements\Query;
21
use Quantum\Libraries\Database\Adapters\Idiorm\Statements\Model;
22
use Quantum\Libraries\Database\Adapters\Idiorm\Statements\Join;
23
use Quantum\Libraries\Database\Contracts\RelationalInterface;
24
use Quantum\Libraries\Database\Exceptions\DatabaseException;
25
use Quantum\Libraries\Database\Contracts\DbalInterface;
26
use InvalidArgumentException;
27
use ORM;
28
use PDO;
29
30
/**
31
 * Class IdiormDbal
32
 * @package Quantum\Libraries\Database
33
 */
34
class IdiormDbal implements DbalInterface, RelationalInterface
35
{
36
37
    use Model;
38
    use Result;
39
    use Criteria;
40
    use Reducer;
41
    use Join;
42
    use Query;
43
44
    /**
45
     * SQLite driver
46
     */
47
    const DRIVER_SQLITE = 'sqlite';
48
49
    /**
50
     * MySQL driver
51
     */
52
    const DRIVER_MYSQL = 'mysql';
53
54
    /**
55
     * PostgresSQL driver
56
     */
57
    const DRIVER_PGSQL = 'pgsql';
58
59
    /**
60
     * Default charset
61
     */
62
    const DEFAULT_CHARSET = 'utf8';
63
64
    /**
65
     * The database table associated with model
66
     * @var string
67
     */
68
    private $table;
69
70
    /**
71
     * Id column of table
72
     * @var string
73
     */
74
    private $idColumn;
75
76
    /**
77
     * Foreign keys
78
     * @var array
79
     */
80
    private $foreignKeys;
81
82
    /**
83
     * Hidden fields
84
     * @var array
85
     */
86
    private $hidden;
87
88
    /**
89
     * Idiorm Patch object
90
     * @var IdiormPatch
91
     */
92
    private $ormPatch = null;
0 ignored issues
show
introduced by
The private property $ormPatch is not used, and could be removed.
Loading history...
93
94
    /**
95
     * ORM Model
96
     * @var object
97
     */
98
    private $ormModel;
99
100
    /**
101
     * Active connection
102
     * @var array|null
103
     */
104
    private static $connection = null;
105
106
    /**
107
     * Operators map
108
     * @var string[]
109
     */
110
    private $operators = [
0 ignored issues
show
introduced by
The private property $operators is not used, and could be removed.
Loading history...
111
        '=' => 'where_equal',
112
        '!=' => 'where_not_equal',
113
        '>' => 'where_gt',
114
        '>=' => 'where_gte',
115
        '<' => 'where_lt',
116
        '<=' => 'where_lte',
117
        'IN' => 'where_in',
118
        'NOT IN' => 'where_not_in',
119
        'LIKE' => 'where_like',
120
        'NOT LIKE' => 'where_not_like',
121
        'NULL' => 'where_null',
122
        'NOT NULL' => 'where_not_null',
123
        '#=#' => null,
124
    ];
125
126
    /**
127
     * ORM Class
128
     * @var string
129
     */
130
    private static $ormClass = ORM::class;
131
132
    /**
133
     * Class constructor
134
     * @param string $table
135
     * @param string $idColumn
136
     * @param array $foreignKeys
137
     * @param array $hidden
138
     */
139
    public function __construct(string $table, string $idColumn = 'id', array $foreignKeys = [], array $hidden = [])
140
    {
141
        $this->table = $table;
142
        $this->idColumn = $idColumn;
143
        $this->foreignKeys = $foreignKeys;
144
        $this->hidden = $hidden;
145
    }
146
147
    /**
148
     * @inheritDoc
149
     */
150
    public static function connect(array $config)
151
    {
152
        $driver = $config['driver'] ?? '';
153
        $charset = $config['charset'] ?? self::DEFAULT_CHARSET;
154
155
        $configuration = self::getBaseConfig($driver, $config) + self::getDriverConfig($driver, $config, $charset);
156
157
        (self::$ormClass)::configure($configuration);
158
159
        self::$connection = (self::$ormClass)::get_config();
160
    }
161
162
    /**
163
     * @inheritDoc
164
     */
165
    public static function getConnection(): ?array
166
    {
167
        return self::$connection;
168
    }
169
170
    /**
171
     * @inheritDoc
172
     */
173
    public static function disconnect()
174
    {
175
        self::$connection = null;
176
        (self::$ormClass)::reset_db();
177
    }
178
179
    /**
180
     * @inheritDoc
181
     */
182
    public function getTable(): string
183
    {
184
        return $this->table;
185
    }
186
187
    /**
188
     * Gets the ORM model
189
     * @return ORM
190
     * @throws DatabaseException
191
     */
192
    public function getOrmModel(): ORM
193
    {
194
        if (!$this->ormModel) {
195
            if (!self::getConnection()) {
196
                throw DatabaseException::missingConfig();
197
            }
198
199
            $this->ormModel = (self::$ormClass)::for_table($this->table)->use_id_column($this->idColumn);
200
        }
201
202
        return $this->ormModel;
203
    }
204
205
    /**
206
     * @param ORM $ormModel
207
     */
208
    protected function updateOrmModel(ORM $ormModel)
209
    {
210
        $this->ormModel = $ormModel;
211
    }
212
213
    /**
214
     * @param string $driver
215
     * @param array $config
216
     * @return array
217
     */
218
    protected static function getBaseConfig(string $driver, array $config): array
219
    {
220
        return [
221
            'connection_string' => self::buildConnectionString($driver, $config),
222
            'logging' => config()->get('debug', false),
223
            'error_mode' => PDO::ERRMODE_EXCEPTION,
224
        ];
225
    }
226
227
    /**
228
     * @param string $driver
229
     * @param array $config
230
     * @param string $charset
231
     * @return array
232
     */
233
    protected static function getDriverConfig(string $driver, array $config, string $charset): array
234
    {
235
        if ($driver === self::DRIVER_MYSQL || $driver === self::DRIVER_PGSQL) {
236
            return [
237
                'username' => $config['username'] ?? null,
238
                'password' => $config['password'] ?? null,
239
                'driver_options' => [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $charset],
240
            ];
241
        }
242
243
        if ($driver === self::DRIVER_SQLITE) {
244
            return [];
245
        }
246
247
        throw new InvalidArgumentException("Unsupported driver: $driver");
248
    }
249
250
    /**
251
     * Builds connection string
252
     * @param string $driver
253
     * @param array $config
254
     * @return string
255
     */
256
    protected static function buildConnectionString(string $driver, array $config): string
257
    {
258
        if ($driver === self::DRIVER_SQLITE) {
259
            return $driver . ':' . ($config['database'] ?? '');
260
        }
261
262
        if ($driver === self::DRIVER_MYSQL || $driver === self::DRIVER_PGSQL) {
263
            $parts = [
264
                'host=' . ($config['host'] ?? ''),
265
                'dbname=' . ($config['dbname'] ?? ''),
266
            ];
267
268
            if (!empty($config['port'])) {
269
                $parts[] = 'port=' . $config['port'];
270
            }
271
272
            if (!empty($config['charset'])) {
273
                $parts[] = 'charset=' . $config['charset'];
274
            }
275
276
            return $driver . ':' . implode(';', $parts);
277
        }
278
279
        throw new InvalidArgumentException("Unsupported driver: $driver");
280
    }
281
}