1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Nip\Database\Connections; |
4
|
|
|
|
5
|
|
|
use Nip\Database\Adapters\HasAdapterTrait; |
6
|
|
|
use Nip\Database\Exception; |
7
|
|
|
use Nip\Database\Metadata\Manager as MetadataManager; |
8
|
|
|
use Nip\Database\Query\AbstractQuery as AbstractQuery; |
9
|
|
|
use Nip\Database\Query\Delete as DeleteQuery; |
10
|
|
|
use Nip\Database\Query\Insert as InsertQuery; |
11
|
|
|
use Nip\Database\Query\Select as SelectQuery; |
12
|
|
|
use Nip\Database\Query\Update as UpdateQuery; |
13
|
|
|
use Nip\Database\Result; |
14
|
|
|
use PDO; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Class Connection |
18
|
|
|
* @package Nip\Database\Connections |
19
|
|
|
*/ |
20
|
|
|
class Connection |
21
|
|
|
{ |
22
|
|
|
use HasAdapterTrait; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* The active PDO connection. |
26
|
|
|
* |
27
|
|
|
* @var PDO |
28
|
|
|
*/ |
29
|
|
|
protected $pdo; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* The name of the connected database. |
33
|
|
|
* |
34
|
|
|
* @var string |
35
|
|
|
*/ |
36
|
|
|
protected $database; |
37
|
|
|
/** |
38
|
|
|
* The table prefix for the connection. |
39
|
|
|
* |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
protected $tablePrefix = ''; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* The database connection configuration options. |
46
|
|
|
* |
47
|
|
|
* @var array |
48
|
|
|
*/ |
49
|
|
|
protected $config = []; |
50
|
|
|
|
51
|
|
|
protected $metadata; |
52
|
|
|
|
53
|
|
|
protected $_query; |
54
|
|
|
|
55
|
|
|
protected $_queries = []; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Create a new database connection instance. |
59
|
|
|
* |
60
|
|
|
* @param \PDO|\Closure $pdo |
61
|
|
|
* @param string $database |
62
|
|
|
* @param string $tablePrefix |
63
|
|
|
* @param array $config |
64
|
25 |
|
*/ |
65
|
|
|
public function __construct($pdo, $database = '', $tablePrefix = '', $config = []) |
66
|
25 |
|
{ |
67
|
|
|
$this->pdo = $pdo; |
|
|
|
|
68
|
|
|
|
69
|
|
|
// First we will setup the default properties. We keep track of the DB |
70
|
|
|
// name we are connected to since it is needed when some reflective |
71
|
25 |
|
// type commands are run such as checking whether a table exists. |
72
|
|
|
$this->database = $database; |
73
|
25 |
|
|
74
|
25 |
|
$this->tablePrefix = $tablePrefix; |
75
|
|
|
$this->config = $config; |
76
|
|
|
|
77
|
|
|
// We need to initialize a query grammar and the query post processors |
78
|
|
|
// which are both very important parts of the database abstractions |
79
|
|
|
// so we initialize these to their default values while starting. |
80
|
|
|
// $this->useDefaultQueryGrammar(); |
81
|
25 |
|
// $this->useDefaultPostProcessor(); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Connects to SQL server |
86
|
|
|
* |
87
|
|
|
* @param string $host |
88
|
|
|
* @param string $user |
89
|
|
|
* @param string $password |
90
|
|
|
* @param string $database |
91
|
|
|
* @param bool $newLink |
92
|
|
|
* |
93
|
|
|
* @return static |
94
|
|
|
*/ |
95
|
|
|
public function connect($host, $user, $password, $database, $newLink = false) |
96
|
|
|
{ |
97
|
|
|
if (!$this->pdo) { |
98
|
|
|
try { |
99
|
|
|
$this->pdo = $this->getAdapter()->connect($host, $user, $password, $database, $newLink); |
100
|
|
|
|
101
|
|
|
if (isset($this->config['charset'])) { |
102
|
|
|
$this->getAdapter()->query('SET CHARACTER SET ' . $this->config['charset']); |
103
|
|
|
$this->getAdapter()->query('SET NAMES ' . $this->config['charset']); |
104
|
|
|
} |
105
|
|
|
if (isset($this->config['modes'])) { |
106
|
|
|
$this->getAdapter()->query("set session sql_mode='{$this->config['modes']}'"); |
107
|
|
|
} |
108
|
|
|
$this->setDatabase($database); |
109
|
|
|
} catch (Exception $e) { |
110
|
|
|
$e->log(); |
|
|
|
|
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
return $this; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* @return string |
119
|
|
|
*/ |
120
|
|
|
public function getDatabase() |
121
|
|
|
{ |
122
|
|
|
return $this->database; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @param string $database |
127
|
|
|
*/ |
128
|
|
|
public function setDatabase($database) |
129
|
|
|
{ |
130
|
|
|
$this->database = $database; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* @return MetadataManager |
135
|
|
|
*/ |
136
|
|
|
public function getMetadata() |
137
|
|
|
{ |
138
|
|
|
if (!$this->metadata) { |
139
|
|
|
$this->metadata = new MetadataManager(); |
140
|
|
|
$this->metadata->setConnection($this); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
return $this->metadata; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Prefixes table names |
148
|
|
|
* |
149
|
|
|
* @param string $table |
150
|
|
|
* @return string |
151
|
|
|
*/ |
152
|
|
|
public function tableName($table) |
153
|
|
|
{ |
154
|
|
|
return $table; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* @param string $type optional |
159
|
13 |
|
* |
160
|
|
|
* @return AbstractQuery|SelectQuery |
161
|
13 |
|
*/ |
162
|
13 |
|
public function newSelect() |
163
|
|
|
{ |
164
|
13 |
|
return $this->newQuery('select'); |
165
|
|
|
} |
166
|
13 |
|
|
167
|
|
|
/** |
168
|
|
|
* @param string $type optional |
169
|
|
|
* @return AbstractQuery|SelectQuery|UpdateQuery|InsertQuery|DeleteQuery |
170
|
|
|
*/ |
171
|
|
|
public function newQuery($type = "select") |
172
|
|
|
{ |
173
|
|
|
$className = '\Nip\Database\Query\\' . inflector()->camelize($type); |
174
|
|
|
$query = new $className(); |
175
|
|
|
/** @var AbstractQuery $query */ |
176
|
|
|
$query->setManager($this); |
177
|
|
|
|
178
|
|
|
return $query; |
179
|
|
|
} |
180
|
1 |
|
|
181
|
|
|
/** |
182
|
1 |
|
* @return InsertQuery |
183
|
|
|
*/ |
184
|
|
|
public function newInsert() |
185
|
|
|
{ |
186
|
|
|
return $this->newQuery('insert'); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* @return UpdateQuery |
191
|
|
|
*/ |
192
|
|
|
public function newUpdate() |
193
|
|
|
{ |
194
|
|
|
return $this->newQuery('update'); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* @return DeleteQuery |
199
|
|
|
*/ |
200
|
|
|
public function newDelete() |
201
|
|
|
{ |
202
|
|
|
return $this->newQuery('delete'); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Executes SQL query |
207
|
|
|
* |
208
|
|
|
* @param mixed|AbstractQuery $query |
209
|
|
|
* @return Result |
210
|
|
|
*/ |
211
|
|
|
public function execute($query) |
212
|
|
|
{ |
213
|
|
|
$this->_queries[] = $query; |
214
|
|
|
|
215
|
|
|
$sql = is_string($query) ? $query : $query->getString(); |
216
|
|
|
|
217
|
|
|
$resultSQL = $this->getAdapter()->execute($sql); |
218
|
|
|
$result = new Result($resultSQL, $this->getAdapter()); |
|
|
|
|
219
|
|
|
$result->setQuery($query); |
220
|
|
|
|
221
|
|
|
return $result; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Gets the ID of the last inserted record |
226
|
|
|
* @return int |
227
|
|
|
*/ |
228
|
|
|
public function lastInsertID() |
229
|
|
|
{ |
230
|
|
|
return $this->getAdapter()->lastInsertID(); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Gets the number of rows affected by the last operation |
235
|
|
|
* @return int |
236
|
|
|
*/ |
237
|
|
|
public function affectedRows() |
238
|
|
|
{ |
239
|
|
|
return $this->getAdapter()->affectedRows(); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* Disconnects from server |
244
|
|
|
*/ |
245
|
|
|
public function disconnect() |
246
|
|
|
{ |
247
|
|
|
if ($this->pdo) { |
248
|
|
|
try { |
249
|
|
|
$this->getAdapter()->disconnect(); |
250
|
|
|
} catch (Exception $e) { |
251
|
|
|
$e->log(); |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* @param null|string $table |
258
|
|
|
* @return mixed |
259
|
|
|
*/ |
260
|
|
|
public function describeTable($table) |
261
|
|
|
{ |
262
|
|
|
return $this->getAdapter()->describeTable($this->protect($table)); |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* Adds backticks to input |
267
|
|
|
* |
268
|
|
|
* @param string $input |
269
|
|
|
* @return string |
270
|
|
|
*/ |
271
|
|
|
public function protect($input) |
272
|
|
|
{ |
273
|
|
|
return str_replace("`*`", "*", '`' . str_replace('.', '`.`', $input) . '`'); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
/** |
277
|
|
|
* @return array |
278
|
|
|
*/ |
279
|
|
|
public function getQueries() |
280
|
|
|
{ |
281
|
|
|
return $this->_queries; |
282
|
|
|
} |
283
|
|
|
} |
284
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.