DbSettings::getUsername()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * this file is part of magerun
4
 *
5
 * @author Tom Klingenberg <https://github.com/ktomk>
6
 */
7
8
namespace N98\Magento;
9
10
use ArrayAccess;
11
use ArrayIterator;
12
use BadMethodCallException;
13
use InvalidArgumentException;
14
use IteratorAggregate;
15
use PDO;
16
use PDOException;
17
use RuntimeException;
18
use SimpleXMLElement;
19
20
/**
21
 * Class DbSettings
22
 *
23
 * Database settings.
24
 *
25
 * The Magento database settings are stored in a SimpleXMLElement structure
26
 *
27
 * @package N98\Magento
28
 */
29
class DbSettings implements ArrayAccess, IteratorAggregate
30
{
31
    /**
32
     * @var string|null known field members
33
     */
34
    private $tablePrefix, $host, $port, $unixSocket, $dbName, $username, $password;
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
35
36
    /**
37
     * @var array field array
38
     */
39
    private $config;
40
41
    /**
42
     * @param string $file path to app/etc/local.xml
43
     */
44
    public function __construct($file)
45
    {
46
        $this->setFile($file);
47
    }
48
49
    /**
50
     * @param string $file path to app/etc/local.xml
51
     *
52
     * @throws InvalidArgumentException if the file is invalid
53
     */
54
    public function setFile($file)
55
    {
56
        if (!is_readable($file)) {
57
            throw new InvalidArgumentException(
58
                sprintf('"app/etc/local.xml"-file %s is not readable', var_export($file, true))
59
            );
60
        }
61
62
        $saved = libxml_use_internal_errors(true);
63
        $config = simplexml_load_file($file);
64
        libxml_use_internal_errors($saved);
65
66
        if (false === $config) {
67
            throw new InvalidArgumentException(
68
                sprintf('Unable to open "app/etc/local.xml"-file %s and parse it as XML', var_export($file, true))
69
            );
70
        }
71
72
        $resources = $config->global->resources;
73
        if (!$resources) {
74
            throw new InvalidArgumentException('DB global resources was not found in "app/etc/local.xml"-file');
75
        }
76
77
        if (!$resources->default_setup->connection) {
78
            throw new InvalidArgumentException('DB settings (default_setup) was not found in "app/etc/local.xml"-file');
79
        }
80
81
        $this->parseResources($resources);
82
    }
83
84
    /**
85
     * helper method to parse config file segment related to the database settings
86
     *
87
     * @param SimpleXMLElement $resources
88
     */
89
    private function parseResources(SimpleXMLElement $resources)
90
    {
91
        // default values
92
        $config = array(
93
            'host'        => null,
94
            'port'        => null,
95
            'unix_socket' => null,
96
            'dbname'      => null,
97
            'username'    => null,
98
            'password'    => null,
99
        );
100
101
        $config = array_merge($config, (array) $resources->default_setup->connection);
102
        $config['prefix'] = (string) $resources->db->table_prefix;
103
104
        // known parameters: host, port, unix_socket, dbname, username, password, options, charset, persistent,
105
        //                   driver_options
106
        //                   (port is deprecated; removed in magento 2, use port in host setting <host>:<port>)
107
108
        unset($config['comment']);
109
110
        /* @see Varien_Db_Adapter_Pdo_Mysql::_connect */
111
        if (strpos($config['host'], '/') !== false) {
112
            $config['unix_socket'] = (string) $config['host'];
113
            $config['host'] = null;
114
            $config['port'] = null;
115
        } elseif (strpos($config['host'], ':') !== false) {
116
            list($config['host'], $config['port']) = explode(':', $config['host']);
117
            $config['unix_socket'] = null;
118
        }
119
120
        $this->config = $config;
121
122
        $this->tablePrefix = $config['prefix'];
123
        $this->host = $config['host'];
124
        $this->port = $config['port'];
125
        $this->unixSocket = $config['unix_socket'];
126
        $this->dbName = $config['dbname'];
127
        $this->username = $config['username'];
128
        $this->password = $config['password'];
129
    }
130
131
    /**
132
     * Get Mysql PDO DSN
133
     *
134
     * @return string
135
     */
136
    public function getDsn()
137
    {
138
        $dsn = 'mysql:';
139
140
        $named = array();
141
142
        // blacklisted in prev. DSN creation: username, password, options, charset, persistent, driver_options, dbname
143
144
        if (isset($this->unixSocket)) {
145
            $named['unix_socket'] = $this->unixSocket;
146
        } else {
147
            $named['host'] = $this->host;
148
            if (isset($this->port)) {
149
                $named['port'] = $this->port;
150
            }
151
        }
152
153
        $options = array();
154
        foreach ($named as $name => $value) {
155
            $options[$name] = "{$name}={$value}";
156
        }
157
158
        return $dsn . implode(';', $options);
159
    }
160
161
    /**
162
     * Connects to the database without initializing magento
163
     *
164
     * @throws RuntimeException if pdo_mysql extension is not installed
165
     * @return PDO
166
     */
167
    public function getConnection()
168
    {
169
        if (!extension_loaded('pdo_mysql')) {
170
            throw new RuntimeException('pdo_mysql extension is not installed');
171
        }
172
173
        $database = $this->getDatabaseName();
174
175
        $connection = new PDO(
176
            $this->getDsn(),
177
            $this->getUsername(),
178
            $this->getPassword()
179
        );
180
181
        /** @link http://bugs.mysql.com/bug.php?id=18551 */
182
        $connection->query("SET SQL_MODE=''");
183
184
        try {
185
            $connection->query('USE ' . $this->quoteIdentifier($database));
186
        } catch (PDOException $e) {
187
            $message = sprintf("Unable to use database '%s': %s %s", $database, get_class($e), $e->getMessage());
188
            throw new RuntimeException($message, 0, $e);
189
        }
190
191
        $connection->query("SET NAMES utf8");
192
193
        $connection->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
194
        $connection->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
195
196
        return $connection;
197
    }
198
199
    public function getMysqlClientToolConnectionString()
200
    {
201
        $segments = array();
202
203
        if (null !== $this->config['unix_socket']) {
204
            $segments[] = '--socket=' . escapeshellarg($this->config['unix_socket']);
205
        } else {
206
            $segments[] = '-h ' . escapeshellarg($this->config['host']);
207
        }
208
209
        $segments[] = '-u' . escapeshellarg($this->config['username']);
210
        if (null !== $this->config['port']) {
211
            $segments[] = '-P' . escapeshellarg($this->config['port']);
212
        }
213
        if (strlen($this->config['password'])) {
214
            $segments[] = '-p' . escapeshellarg($this->config['password']);
215
        }
216
        $segments[] = escapeshellarg($this->config['dbname']);
217
218
        return implode(' ', $segments);
219
    }
220
221
    /**
222
     * Mysql quoting of an identifier
223
     *
224
     * @param string $identifier UTF-8 encoded
225
     *
226
     * @return string quoted identifier
227
     */
228
    private function quoteIdentifier($identifier)
229
    {
230
        $quote = '`'; // le backtique
231
232
        $pattern = '~^(?:[\x1-\x7F]|[\xC2-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2})+$~';
233
234
        if (!preg_match($pattern, $identifier)) {
235
            throw new InvalidArgumentException(
236
                sprintf(
237
                    'Invalid identifier, must not contain NUL and must be UTF-8 encoded in the BMP: %s (hex: %s)',
238
                    var_export($identifier, true),
239
                    bin2hex($identifier)
240
                )
241
            );
242
        }
243
244
        return $quote . strtr($identifier, array($quote => $quote . $quote)) . $quote;
245
    }
246
247
    /**
248
     * @return bool
249
     */
250
    public function isSocketConnect()
251
    {
252
        return isset($this->config['unix_socket']);
253
    }
254
255
    /**
256
     * @return string table prefix, null if not in the settings (no or empty prefix)
257
     */
258
    public function getTablePrefix()
259
    {
260
        return $this->tablePrefix;
261
    }
262
263
    /**
264
     * @return string hostname, null if there is no hostname setup (e.g. unix_socket)
265
     */
266
    public function getHost()
267
    {
268
        return $this->host;
269
    }
270
271
    /**
272
     * @return string port, null if not setup
273
     */
274
    public function getPort()
275
    {
276
        return $this->port;
277
    }
278
279
    /**
280
     * @return string username
281
     */
282
    public function getUsername()
283
    {
284
        return $this->username;
285
    }
286
287
    /**
288
     * @return string password
289
     */
290
    public function getPassword()
291
    {
292
        return $this->password;
293
    }
294
295
    /**
296
     * @return string unix socket, null if not in use
297
     */
298
    public function getUnixSocket()
299
    {
300
        return $this->unixSocket;
301
    }
302
303
    /**
304
     * content of previous $dbSettings field of the DatabaseHelper
305
     *
306
     * @return array
307
     */
308
    public function getConfig()
309
    {
310
        return $this->config;
311
    }
312
313
    /**
314
     * @return string of the database identifier, null if not in use
315
     */
316
    public function getDatabaseName()
317
    {
318
        return $this->dbName;
319
    }
320
321
    /*
322
     * ArrayAccess interface
323
     */
324
325
    /**
326
     * @return boolean true on success or false on failure.
327
     */
328
    public function offsetExists($offset)
329
    {
330
        return isset($this->config[$offset]);
331
    }
332
333
    /**
334
     * @return mixed Can return all value types.
335
     */
336
    public function offsetGet($offset)
337
    {
338
        if (isset($this->config[$offset])) {
339
            return $this->config[$offset];
340
        }
341
342
        return;
343
    }
344
345
    /**
346
     * @param mixed $offset
347
     * @param mixed $value
348
     *
349
     * @throws BadMethodCallException
350
     */
351
    public function offsetSet($offset, $value)
352
    {
353
        throw new BadMethodCallException('dbSettings are read-only');
354
    }
355
356
    /**
357
     * @param mixed $offset
358
     *
359
     * @throws BadMethodCallException
360
     */
361
    public function offsetUnset($offset)
362
    {
363
        throw new BadMethodCallException('dbSettings are read-only');
364
    }
365
366
    /*
367
     * IteratorAggregate
368
     */
369
370
    /**
371
     * @return ArrayIterator
372
     */
373
    public function getIterator()
374
    {
375
        return new ArrayIterator($this->config);
376
    }
377
}
378