-
Notifications
You must be signed in to change notification settings - Fork 0
/
LightDatabasePdoWrapper.php
208 lines (178 loc) · 6.7 KB
/
LightDatabasePdoWrapper.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<?php
namespace Ling\Light_Database;
use Ling\Light\Events\LightEvent;
use Ling\Light\ServiceContainer\LightServiceContainerInterface;
use Ling\Light_Database\Exception\LightDatabaseException;
use Ling\Light_Events\Service\LightEventsService;
use Ling\SimplePdoWrapper\SimplePdoWrapper;
/**
* The LightDatabasePdoWrapper class.
*/
class LightDatabasePdoWrapper extends SimplePdoWrapper
{
/**
* This property holds the pdoException thrown during the connection,
* or null if such exception was not thrown.
*
* @var \PDOException|null
*/
protected $pdoException;
/**
* This property holds the container for this instance.
* @var LightServiceContainerInterface
*/
protected $container;
/**
* Builds the LightDatabasePdoWrapper instance.
*/
public function __construct()
{
parent::__construct();
$this->pdoException = null;
$this->container = null;
}
/**
* Creates the pdo instance and attaches it to this instance.
* The settings array expects the following keys:
*
* - ?pdo_driver: the pdo driver to use (i.e. mysql, sqlite, ...). The default is mysql.
* See the pdo documentation for more details.
* - pdo_database: the name of the (main) database.
* - pdo_user: the name of the database user.
* - pdo_pass: the password for the database user.
* - ?pdo_host: the host of the pdo dsn if any. For instance: localhost, or 127.0.0.1.
* By default the value will be localhost.
* - ?pdo_socket: the path to socket to use (this replaces the pdo_host setting).
* - ?pdo_port: the number of the port to connect to.
* - ?pdo_options: an array of options to pass to the pdo instance.
* Available options are the based on the php pdo options.
* The currently implemented options are the following:
* - persistent: bool
* - errmode: string (warning|exception|silent)
* - initCommand: string, example: SET NAMES 'UTF8' (the initCommand option is specific to the mysql driver)
*
*
*
* Note: as for now, only the driver invocation technique is used to create the DSN (i.e. the
* uri invocation and aliasing technique are not yet implemented).
*
*
* If the pdo connection fails, a LightDatabaseException exception is thrown,
* which doesn't reveal the pdo credentials, for security reason.
* Note: if you want to get the error message of the original exception, you can access it using the
* getConnectionException method.
*
*
*
* @param array $settings
* @throws LightDatabaseException
*
*/
public function init(array $settings)
{
$driver = $settings['pdo_driver'] ?? 'mysql';
//--------------------------------------------
// DSN
//--------------------------------------------
$dsn = $driver . ":dbname=" . $settings['pdo_database'];
if (array_key_exists('pdo_socket', $settings)) {
$dsn .= ';unix_socket=' . $settings['pdo_socket'];
} else {
$host = $settings['pdo_host'] ?? "localhost";
$dsn .= ';host=' . $host;
}
if (array_key_exists('pdo_port', $settings)) {
$dsn .= ';port=' . $settings['pdo_port'];
}
//--------------------------------------------
// CONNEXION
//--------------------------------------------
$options = [];
if (array_key_exists("pdo_options", $settings)) {
foreach ($settings['pdo_options'] as $k => $v) {
switch ($k) {
case "errmode":
if ('warning' === $v) {
$v = \PDO::ERRMODE_WARNING;
} elseif ('exception' === $v) {
$v = \PDO::ERRMODE_EXCEPTION;
} elseif ('silent' === $v) {
$v = \PDO::ERRMODE_SILENT;
} else {
throw new LightDatabaseException("Unknown errmode: $v (possible values are warning, exception or silent.");
}
$options[\PDO::ATTR_ERRMODE] = $v;
break;
case "initCommand":
$options[\PDO::MYSQL_ATTR_INIT_COMMAND] = $v;
break;
case "persistent":
$options[\PDO::ATTR_PERSISTENT] = $v;
break;
}
}
}
try {
$pdo = new \PDO($dsn, $settings['pdo_user'], $settings['pdo_pass'], $options);
$this->setConnexion($pdo);
} catch (\PDOException $e) {
$this->pdoException = $e;
throw new LightDatabaseException("A problem occurred while trying to connect to the database.");
}
}
/**
* Returns the error message of the original exception thrown if the pdo connection failed during call to the
* init method.
* Or an empty string by default, or if the connexion went ok.
*
* @return \PDOException|null
*/
public function getConnectionException(): ?\PDOException
{
return $this->pdoException;
}
//--------------------------------------------
//
//--------------------------------------------
/**
* Sets the container.
*
* @param LightServiceContainerInterface $container
*/
public function setContainer(LightServiceContainerInterface $container)
{
$this->container = $container;
}
//--------------------------------------------
//
//--------------------------------------------
/**
* @overrides
*/
protected function onSuccess(string $type, string $table, string $query, array $arguments, $return = true)
{
$eventType = $type;
if ('insert' === $eventType || 'replace' === $eventType) {
$eventType = 'create';
}
//--------------------------------------------
// dispatching the event
//--------------------------------------------
$event = LightEvent::createByContainer($this->container);
$event->setVar('table', $table);
$event->setVar('action', $type);
$event->setVar('query', $query);
$event->setVar('arguments', $arguments);
$event->setVar('return', $return);
/**
* @var $dispatcher LightEventsService
*/
$dispatcher = $this->container->get("events");
$eventName = 'Light_Database.' . implode('_', [
'on',
$table,
$eventType,
]);
$dispatcher->dispatch($eventName, $event);
}
}