PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 1.3.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v1.3.1
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Tracker / Db / Pdo / Mysql.php
matomo / app / core / Tracker / Db / Pdo Last commit date
Mysql.php 6 years ago Pgsql.php 6 years ago
Mysql.php
331 lines
1 <?php
2 /**
3 * Piwik - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9 namespace Piwik\Tracker\Db\Pdo;
10
11 use Exception;
12 use PDO;
13 use PDOException;
14 use PDOStatement;
15 use Piwik\Tracker\Db;
16 use Piwik\Tracker\Db\DbException;
17
18 /**
19 * PDO MySQL wrapper
20 *
21 */
22 class Mysql extends Db
23 {
24 /**
25 * @var PDO
26 */
27 protected $connection = null;
28 protected $dsn;
29 protected $username;
30 protected $password;
31 protected $charset;
32
33 protected $mysqlOptions = array();
34
35
36 protected $activeTransaction = false;
37
38 /**
39 * Builds the DB object
40 *
41 * @param array $dbInfo
42 * @param string $driverName
43 */
44 public function __construct($dbInfo, $driverName = 'mysql')
45 {
46 if (isset($dbInfo['unix_socket']) && substr($dbInfo['unix_socket'], 0, 1) == '/') {
47 $this->dsn = $driverName . ':dbname=' . $dbInfo['dbname'] . ';unix_socket=' . $dbInfo['unix_socket'];
48 } elseif (!empty($dbInfo['port']) && substr($dbInfo['port'], 0, 1) == '/') {
49 $this->dsn = $driverName . ':dbname=' . $dbInfo['dbname'] . ';unix_socket=' . $dbInfo['port'];
50 } else {
51 $this->dsn = $driverName . ':dbname=' . $dbInfo['dbname'] . ';host=' . $dbInfo['host'] . ';port=' . $dbInfo['port'];
52 }
53
54 $this->username = $dbInfo['username'];
55 $this->password = $dbInfo['password'];
56
57 if (isset($dbInfo['charset'])) {
58 $this->charset = $dbInfo['charset'];
59 $this->dsn .= ';charset=' . $this->charset;
60 }
61
62
63 if (isset($dbInfo['enable_ssl']) && $dbInfo['enable_ssl']) {
64
65 if (!empty($dbInfo['ssl_key'])) {
66 $this->mysqlOptions[PDO::MYSQL_ATTR_SSL_KEY] = $dbInfo['ssl_key'];
67 }
68 if (!empty($dbInfo['ssl_cert'])) {
69 $this->mysqlOptions[PDO::MYSQL_ATTR_SSL_CERT] = $dbInfo['ssl_cert'];
70 }
71 if (!empty($dbInfo['ssl_ca'])) {
72 $this->mysqlOptions[PDO::MYSQL_ATTR_SSL_CA] = $dbInfo['ssl_ca'];
73 }
74 if (!empty($dbInfo['ssl_ca_path'])) {
75 $this->mysqlOptions[PDO::MYSQL_ATTR_SSL_CAPATH] = $dbInfo['ssl_ca_path'];
76 }
77 if (!empty($dbInfo['ssl_cipher'])) {
78 $this->mysqlOptions[PDO::MYSQL_ATTR_SSL_CIPHER] = $dbInfo['ssl_cipher'];
79 }
80 if (!empty($dbInfo['ssl_no_verify']) && defined('PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')) {
81 $this->mysqlOptions[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
82 }
83 }
84
85 }
86
87 public function __destruct()
88 {
89 $this->connection = null;
90 }
91
92 /**
93 * Connects to the DB
94 *
95 * @throws Exception if there was an error connecting the DB
96 */
97 public function connect()
98 {
99 if (self::$profiling) {
100 $timer = $this->initProfiler();
101 }
102
103 // Make sure MySQL returns all matched rows on update queries including
104 // rows that actually didn't have to be updated because the values didn't
105 // change. This matches common behaviour among other database systems.
106 // See #6296 why this is important in tracker
107 $this->mysqlOptions[PDO::MYSQL_ATTR_FOUND_ROWS] = true;
108 $this->mysqlOptions[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
109
110
111
112 $this->connection = @new PDO($this->dsn, $this->username, $this->password, $this->mysqlOptions);
113
114 // we may want to setAttribute(PDO::ATTR_TIMEOUT ) to a few seconds (default is 60) in case the DB is locked
115 // the matomo.php would stay waiting for the database... bad!
116 // we delete the password from this object "just in case" it could be printed
117 $this->password = '';
118
119 /*
120 * Lazy initialization via MYSQL_ATTR_INIT_COMMAND depends
121 * on mysqlnd support, PHP version, and OS.
122 * see ZF-7428 and http://bugs.php.net/bug.php?id=47224
123 */
124 if (!empty($this->charset)) {
125 $sql = "SET NAMES '" . $this->charset . "'";
126 $this->connection->exec($sql);
127 }
128
129 if (self::$profiling && isset($timer)) {
130 $this->recordQueryProfile('connect', $timer);
131 }
132 }
133
134 /**
135 * Disconnects from the server
136 */
137 public function disconnect()
138 {
139 $this->connection = null;
140 }
141
142 /**
143 * Returns an array containing all the rows of a query result, using optional bound parameters.
144 *
145 * @param string $query Query
146 * @param array $parameters Parameters to bind
147 * @return array|bool
148 * @see query()
149 * @throws Exception|DbException if an exception occurred
150 */
151 public function fetchAll($query, $parameters = array())
152 {
153 try {
154 $sth = $this->query($query, $parameters);
155 if ($sth === false) {
156 return false;
157 }
158 return $sth->fetchAll(PDO::FETCH_ASSOC);
159 } catch (PDOException $e) {
160 throw new DbException("Error query: " . $e->getMessage());
161 }
162 }
163
164 /**
165 * Fetches the first column of all SQL result rows as an array.
166 *
167 * @param string $sql An SQL SELECT statement.
168 * @param mixed $bind Data to bind into SELECT placeholders.
169 * @throws \Piwik\Tracker\Db\DbException
170 * @return string
171 */
172 public function fetchCol($sql, $bind = array())
173 {
174 try {
175 $sth = $this->query($sql, $bind);
176 if ($sth === false) {
177 return false;
178 }
179 $result = $sth->fetchAll(PDO::FETCH_COLUMN, 0);
180 return $result;
181 } catch (PDOException $e) {
182 throw new DbException("Error query: " . $e->getMessage());
183 }
184 }
185
186 /**
187 * Returns the first row of a query result, using optional bound parameters.
188 *
189 * @param string $query Query
190 * @param array $parameters Parameters to bind
191 * @return bool|mixed
192 * @see query()
193 * @throws Exception|DbException if an exception occurred
194 */
195 public function fetch($query, $parameters = array())
196 {
197 try {
198 $sth = $this->query($query, $parameters);
199 if ($sth === false) {
200 return false;
201 }
202 return $sth->fetch(PDO::FETCH_ASSOC);
203 } catch (PDOException $e) {
204 throw new DbException("Error query: " . $e->getMessage());
205 }
206 }
207
208 /**
209 * Executes a query, using optional bound parameters.
210 *
211 * @param string $query Query
212 * @param array|string $parameters Parameters to bind array('idsite'=> 1)
213 * @return PDOStatement|bool PDOStatement or false if failed
214 * @throws DbException if an exception occurred
215 */
216 public function query($query, $parameters = array())
217 {
218 if (is_null($this->connection)) {
219 return false;
220 }
221
222 try {
223 if (self::$profiling) {
224 $timer = $this->initProfiler();
225 }
226
227 if (!is_array($parameters)) {
228 $parameters = array($parameters);
229 }
230 $sth = $this->connection->prepare($query);
231 $sth->execute($parameters);
232
233 if (self::$profiling && isset($timer)) {
234 $this->recordQueryProfile($query, $timer);
235 }
236 return $sth;
237 } catch (PDOException $e) {
238 $message = $e->getMessage() . " In query: $query Parameters: " . var_export($parameters, true);
239 throw new DbException("Error query: " . $message, (int) $e->getCode());
240 }
241 }
242
243 /**
244 * Returns the last inserted ID in the DB
245 * Wrapper of PDO::lastInsertId()
246 *
247 * @return int
248 */
249 public function lastInsertId()
250 {
251 return $this->connection->lastInsertId();
252 }
253
254 /**
255 * Test error number
256 *
257 * @param Exception $e
258 * @param string $errno
259 * @return bool
260 */
261 public function isErrNo($e, $errno)
262 {
263 return \Piwik\Db\Adapter\Pdo\Mysql::isPdoErrorNumber($e, $errno);
264 }
265
266 /**
267 * Return number of affected rows in last query
268 *
269 * @param mixed $queryResult Result from query()
270 * @return int
271 */
272 public function rowCount($queryResult)
273 {
274 return $queryResult->rowCount();
275 }
276
277 /**
278 * Start Transaction
279 * @return string TransactionID
280 */
281 public function beginTransaction()
282 {
283 if (!$this->activeTransaction === false) {
284 return;
285 }
286
287 if ($this->connection->beginTransaction()) {
288 $this->activeTransaction = uniqid();
289 return $this->activeTransaction;
290 }
291 }
292
293 /**
294 * Commit Transaction
295 * @param $xid
296 * @throws DbException
297 * @internal param TransactionID $string from beginTransaction
298 */
299 public function commit($xid)
300 {
301 if ($this->activeTransaction != $xid || $this->activeTransaction === false) {
302 return;
303 }
304
305 $this->activeTransaction = false;
306
307 if (!$this->connection->commit()) {
308 throw new DbException("Commit failed");
309 }
310 }
311
312 /**
313 * Rollback Transaction
314 * @param $xid
315 * @throws DbException
316 * @internal param TransactionID $string from beginTransaction
317 */
318 public function rollBack($xid)
319 {
320 if ($this->activeTransaction != $xid || $this->activeTransaction === false) {
321 return;
322 }
323
324 $this->activeTransaction = false;
325
326 if (!$this->connection->rollBack()) {
327 throw new DbException("Rollback failed");
328 }
329 }
330 }
331