public static function parseDSN($dsn)
{
$parsed = array('driver' => false, 'user' => false, 'password' => false, 'host' => false, 'port' => false, 'unix_socket' => false, 'dbname' => false, 'memory' => false, 'path' => false);
// Find driver and dbsyntax
if (($pos = strpos($dsn, '://')) !== false) {
$str = substr($dsn, 0, $pos);
$dsn = substr($dsn, $pos + 3);
} else {
$str = $dsn;
$dsn = null;
}
// Get driver and dbsyntax
// $str => driver(dbsyntax)
if (preg_match('|^(.+?)\\((.*?)\\)$|', $str, $arr)) {
$parsed['driver'] = $arr[1];
} else {
$parsed['driver'] = $str;
}
if (!count($dsn)) {
return $parsed;
}
// Get (if found): username and password
// $dsn => username:password@protocol+host/database
if (($at = strrpos((string) $dsn, '@')) !== false) {
$str = substr($dsn, 0, $at);
$dsn = substr($dsn, $at + 1);
if (($pos = strpos($str, ':')) !== false) {
$parsed['user'] = rawurldecode(substr($str, 0, $pos));
$parsed['password'] = rawurldecode(substr($str, $pos + 1));
} else {
$parsed['user'] = rawurldecode($str);
}
}
// Find protocol and host
if (preg_match('|^([^(]+)\\((.*?)\\)/?(.*?)$|', $dsn, $match)) {
// $dsn => proto(proto_opts)/database
$proto = $match[1];
$proto_opts = $match[2] ? $match[2] : false;
$dsn = $match[3];
} else {
// $dsn => protocol+host/database (old format)
if (strpos($dsn, '+') !== false) {
list($proto, $dsn) = explode('+', $dsn, 2);
}
if (strpos($dsn, '/') !== false) {
list($proto_opts, $dsn) = explode('/', $dsn, 2);
} else {
$proto_opts = $dsn;
$dsn = null;
}
}
// process the different protocol options
$protocol = !empty($proto) ? $proto : 'tcp';
$proto_opts = rawurldecode($proto_opts);
if ($protocol === 'tcp') {
if (strpos($proto_opts, ':') !== false) {
list($parsed['host'], $parsed['port']) = explode(':', $proto_opts);
} else {
$parsed['host'] = $proto_opts;
}
} elseif ($protocol === 'unix') {
$parsed['unix_socket'] = $proto_opts;
}
// Get dabase if any
// $dsn => database
if ($dsn) {
if (($pos = strpos($dsn, '?')) === false) {
// /database
$parsed['dbname'] = rawurldecode($dsn);
} else {
// /database?param1=value1¶m2=value2
$parsed['dbname'] = rawurldecode(substr($dsn, 0, $pos));
$dsn = substr($dsn, $pos + 1);
if (strpos($dsn, '&') !== false) {
$opts = explode('&', $dsn);
} else {
$opts = array($dsn);
}
foreach ($opts as $opt) {
list($key, $value) = explode('=', $opt);
if (!isset($parsed[$key])) {
// don't allow params overwrite
$parsed[$key] = rawurldecode($value);
}
}
}
}
if ($parsed['driver'] === 'sqlite') {
if (isset($parsed['port']) && $parsed['port'] === 'memory') {
$parsed['memory'] = true;
unset($parsed['port']);
unset($parsed['host']);
} elseif (isset($parsed['dbname'])) {
$parsed['path'] = $parsed['dbname'];
unset($parsed['dbname']);
unset($parsed['host']);
}
}
$driverMap = array('mysql' => 'pdo_mysql', 'pgsql' => 'pdo_pgsql', 'sqlite' => 'pdo_sqlite');
if (isset($driverMap[$parsed['driver']])) {
$parsed['driver'] = $driverMap[$parsed['driver']];
}
return array_filter($parsed, function ($element) {
return $element !== false;
});
}