public static function factory($dsn, string $username = '', string $password = '', $options = []) : Database
{
$post_query = null;
$dbEngine = '';
if (\is_array($dsn)) {
list($dsn, $dbEngine, $username, $password) = self::flattenDSN($dsn, $username, $password);
} elseif (!\is_string($dsn)) {
throw new \TypeError(\__('DSN must be string or array'));
} elseif (\strpos($dsn, ':') !== false) {
$dbEngine = \explode(':', $dsn)[0];
}
// Database engine specific DSN addendums
switch ($dbEngine) {
case 'mysql':
if (\strpos($dsn, ';charset=') === false) {
// If no charset is specified, default to UTF-8
$dsn .= ';charset=utf8';
}
break;
}
try {
if (empty($username) && empty($password) && empty($options)) {
$pdo = new \PDO($dsn);
} else {
$pdo = new \PDO($dsn, $username, $password, $options);
}
} catch (\PDOException $e) {
// Don't leak the DB password in a stack trace:
throw new DBAlert\DBException(\trk('errors.database.pdo_exception'));
}
// Let's turn off emulated prepares
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
if (!empty($post_query)) {
$pdo->exec($post_query);
}
return new Database($pdo, $dbEngine);
}