Query/src/Query/ConnectionManager.php

264 lines
5.8 KiB
PHP

<?php
/**
* Query
*
* Free Query Builder / Database Abstraction Layer
*
* @package Query
* @author Timothy J. Warren
* @copyright Copyright (c) 2012 - 2015
* @link https://github.com/aviat4ion/Query
* @license http://philsturgeon.co.uk/code/dbad-license
*/
// --------------------------------------------------------------------------
namespace Query;
/**
* Connection manager class to manage connections for the
* Query method
*
* @package Query
* @subpackage Core
*/
final class ConnectionManager {
/**
* Map of named database connections
* @var array
*/
private $connections = [];
/**
* Class instance variable
* @var ConnectionManager
*/
private static $instance = NULL;
// --------------------------------------------------------------------------
/**
* Private constructor to prevent multiple instances
* @codeCoverageIgnore
*/
private function __construct()
{
}
// --------------------------------------------------------------------------
/**
* Private clone method to prevent cloning
* @throws \DomainException
*/
public function __clone()
{
throw new \DomainException("Can't clone singleton");
}
// --------------------------------------------------------------------------
/**
* Prevent serialization of this object
* @throws \DomainException
*/
public function __sleep()
{
throw new \DomainException("No serializing of singleton");
}
// --------------------------------------------------------------------------
/**
* Make sure serialize/deserialize doesn't work
* @throws \DomainException
*/
public function __wakeup()
{
throw new \DomainException("Can't unserialize singleton");
}
// --------------------------------------------------------------------------
/**
* Return a connection manager instance
*
* @staticvar null $instance
* @return ConnectionManager
*/
public static function get_instance()
{
if (self::$instance === NULL)
{
self::$instance = new self();
}
return self::$instance;
}
// --------------------------------------------------------------------------
/**
* Returns the connection specified by the name given
*
* @param string|array|object $name
* @return QueryBuilder
* @throws \InvalidArgumentException
*/
public function get_connection($name = '')
{
// If the parameter is a string, use it as an array index
if (is_scalar($name) && isset($this->connections[$name]))
{
return $this->connections[$name];
}
elseif (empty($name) && ! empty($this->connections)) // Otherwise, return the last one
{
return end($this->connections);
}
// You should actually connect before trying to get a connection...
throw new \InvalidArgumentException("The specified connection does not exist");
}
// --------------------------------------------------------------------------
/**
* Parse the passed parameters and return a connection
*
* @param \stdClass $params
* @return QueryBuilder
*/
public function connect(\stdClass $params)
{
list($dsn, $dbtype, $params, $options) = $this->parse_params($params);
$dbtype = ucfirst($dbtype);
$driver = "\\Query\\Drivers\\{$dbtype}\\Driver";
// Create the database connection
$db = ( ! empty($params->user))
? new $driver($dsn, $params->user, $params->pass, $options)
: new $driver($dsn, '', '', $options);
// Set the table prefix, if it exists
if (isset($params->prefix))
{
$db->set_table_prefix($params->prefix);
}
// Create Query Builder object
$conn = new QueryBuilder($db, new QueryParser($db));
// Save it for later
if (isset($params->alias))
{
$this->connections[$params->alias] = $conn;
}
else
{
$this->connections[] = $conn;
}
return $conn;
}
// --------------------------------------------------------------------------
/**
* Parses params into a dsn and option array
*
* @param \stdClass $params
* @return array
* @throws BadDBDriverException
*/
public function parse_params(\stdClass $params)
{
$params->type = strtolower($params->type);
$dbtype = ($params->type !== 'postgresql') ? $params->type : 'pgsql';
$dbtype = ucfirst($dbtype);
// Make sure the class exists
if ( ! class_exists("\\Query\\Drivers\\{$dbtype}\\Driver"))
{
throw new BadDBDriverException('Database driver does not exist, or is not supported');
}
// Set additional PDO options
$options = [];
if (isset($params->options))
{
$options = (array) $params->options;
}
// Create the dsn for the database to connect to
if (strtolower($dbtype) === 'firebird')
{
$dsn = "{$params->host}:{$params->file}";
}
else if(strtolower($dbtype) === 'sqlite')
{
$dsn = $params->file;
}
else if(strtolower($dbtype) === 'oci')
{
$dsn = "dbname=//{$params->host}:{$params->port}/{$params->database}";
}
else
{
$dsn = $this->create_dsn($dbtype, $params);
}
return [$dsn, $dbtype, $params, $options];
}
// --------------------------------------------------------------------------
/**
* Create the dsn from the db type and params
*
* @param string $dbtype
* @param \stdClass $params
* @return string
*/
private function create_dsn($dbtype, \stdClass $params)
{
if (strtolower($dbtype) === 'pdo_firebird')
{
$dbtype = 'firebird';
}
$pairs = [];
if ( ! empty($params->database))
{
$pairs[] = implode('=', ['dbname', $params->database]);
}
$skip = [
'name' => 'name',
'pass' => 'pass',
'user' => 'user',
'type' => 'type',
'prefix' => 'prefix',
'options' => 'options',
'database' => 'database',
'alias' => 'alias'
];
foreach($params as $key => $val)
{
if (( ! array_key_exists($key, $skip)) && ( ! empty($val)))
{
$pairs[] = implode('=', [$key, $val]);
}
}
return strtolower($dbtype) . ':' . implode(';', $pairs);
}
}
// End of connection_manager.php