Query/src/ConnectionManager.php

241 lines
5.1 KiB
PHP
Raw Normal View History

2016-10-12 22:12:25 -04:00
<?php declare(strict_types=1);
/**
* Query
*
2016-09-07 13:17:17 -04:00
* SQL Query Builder / Database Abstraction Layer
*
2020-04-10 20:54:31 -04:00
* PHP version 7.4
2016-09-07 13:17:17 -04:00
*
* @package Query
* @author Timothy J. Warren <tim@timshomepage.net>
2020-03-18 11:31:56 -04:00
* @copyright 2012 - 2020 Timothy J. Warren
2016-09-07 13:17:17 -04:00
* @license http://www.opensource.org/licenses/mit-license.html MIT License
2019-12-11 16:49:42 -05:00
* @link https://git.timshomepage.net/aviat/Query
* @version 3.0.0
*/
2014-04-02 17:08:50 -04:00
namespace Query;
2016-10-12 20:32:23 -04:00
use DomainException;
use stdClass;
2016-10-12 20:32:23 -04:00
/**
* Connection manager class to manage connections for the
* Query method
*/
2015-11-10 10:12:23 -05:00
final class ConnectionManager {
/**
* Map of named database connections
* @var array
*/
private array $connections = [];
/**
* Class instance variable
* @var ConnectionManager|null
*/
private static ?ConnectionManager $instance = NULL;
/**
2014-03-31 16:01:58 -04:00
* Private constructor to prevent multiple instances
* @codeCoverageIgnore
*/
2016-10-12 22:12:25 -04:00
private function __construct()
2016-10-12 20:32:23 -04:00
{
}
2014-03-31 16:01:58 -04:00
/**
* Private clone method to prevent cloning
2016-09-07 14:22:52 -04:00
*
2016-10-12 20:32:23 -04:00
* @throws DomainException
2016-09-07 14:22:52 -04:00
* @return void
2014-03-31 16:01:58 -04:00
*/
public function __clone()
{
2016-10-12 20:32:23 -04:00
throw new DomainException("Can't clone singleton");
}
/**
* Prevent serialization of this object
2016-09-07 14:22:52 -04:00
*
2016-10-12 20:32:23 -04:00
* @throws DomainException
*/
2020-12-03 14:32:30 -05:00
public function __sleep()
{
throw new DomainException('No serializing of singleton');
}
/**
2014-04-22 14:02:54 -04:00
* Make sure serialize/deserialize doesn't work
2016-09-07 14:22:52 -04:00
*
2016-10-12 20:32:23 -04:00
* @throws DomainException
2016-09-07 14:22:52 -04:00
* @return void
*/
public function __wakeup(): void
{
2016-10-12 20:32:23 -04:00
throw new DomainException("Can't unserialize singleton");
}
/**
* Return a connection manager instance
*
* @staticvar null $instance
2015-11-10 20:58:32 -05:00
* @return ConnectionManager
*/
2016-10-13 21:55:23 -04:00
public static function getInstance(): ConnectionManager
{
2016-09-07 13:10:03 -04:00
if (self::$instance === NULL)
2015-11-11 09:25:21 -05:00
{
self::$instance = new self();
}
return self::$instance;
}
/**
* Returns the connection specified by the name given
*
* @param string|array|object $name
2016-10-13 21:55:23 -04:00
* @return QueryBuilderInterface
* @throws Exception\NonExistentConnectionException
*/
2016-10-13 21:55:23 -04:00
public function getConnection($name = ''): QueryBuilderInterface
{
2014-04-22 14:02:54 -04:00
// If the parameter is a string, use it as an array index
if (is_scalar($name) && isset($this->connections[$name]))
{
return $this->connections[$name];
}
2019-12-11 16:49:06 -05:00
if (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 Exception\NonExistentConnectionException('The specified connection does not exist');
}
/**
* Parse the passed parameters and return a connection
*
* @param array|object $params
* @throws Exception\BadDBDriverException
2016-10-13 21:55:23 -04:00
* @return QueryBuilderInterface
*/
2018-01-26 08:39:30 -05:00
public function connect($params): QueryBuilderInterface
{
2019-12-11 16:49:06 -05:00
[$dsn, $dbType, $params, $options] = $this->parseParams($params);
2019-12-11 16:49:06 -05:00
$dbType = ucfirst($dbType);
$driver = "\\Query\\Drivers\\{$dbType}\\Driver";
2014-04-02 17:08:50 -04:00
// Create the database connection
$db = ! empty($params->user)
2014-04-02 17:08:50 -04:00
? new $driver($dsn, $params->user, $params->pass, $options)
: new $driver($dsn, '', '', $options);
// Set the table prefix, if it exists
if (isset($params->prefix))
{
2016-10-13 21:55:23 -04:00
$db->setTablePrefix($params->prefix);
}
// Create Query Builder object
2015-11-10 10:12:23 -05:00
$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 array|object $rawParams
2019-12-11 16:49:06 -05:00
* @return array
* @throws Exception\BadDBDriverException
*/
public function parseParams($rawParams): array
{
$params = (object) $rawParams;
$params->type = strtolower($params->type);
$dbType = ($params->type === 'postgresql') ? 'pgsql' : $params->type;
2019-12-11 16:49:06 -05:00
$dbType = ucfirst($dbType);
// Make sure the class exists
2019-12-11 16:49:06 -05:00
if ( ! class_exists("\\Query\\Drivers\\{$dbType}\\Driver"))
{
throw new Exception\BadDBDriverException('Database driver does not exist, or is not supported');
}
// Set additional PDO options
2016-09-07 13:10:03 -04:00
$options = [];
if (isset($params->options))
{
$options = (array) $params->options;
}
// Create the dsn for the database to connect to
2019-12-11 16:49:06 -05:00
if(strtolower($dbType) === 'sqlite')
2015-07-17 16:01:41 -04:00
{
$dsn = $params->file;
}
else
{
2019-12-11 16:49:06 -05:00
$dsn = $this->createDsn($dbType, $params);
}
2019-12-11 16:49:06 -05:00
return [$dsn, $dbType, $params, $options];
}
/**
* Create the dsn from the db type and params
*
2018-01-24 13:14:03 -05:00
* @codeCoverageIgnore
2019-12-11 16:49:06 -05:00
* @param string $dbType
* @param stdClass $params
* @return string
*/
private function createDsn(string $dbType, stdClass $params): string
{
2016-09-07 13:10:03 -04:00
$pairs = [];
2015-07-17 16:01:41 -04:00
if ( ! empty($params->database))
{
2016-09-07 13:10:03 -04:00
$pairs[] = implode('=', ['dbname', $params->database]);
2015-07-17 16:01:41 -04:00
}
2016-09-07 13:10:03 -04:00
$skip = [
2015-07-17 16:01:41 -04:00
'name' => 'name',
'pass' => 'pass',
'user' => 'user',
'type' => 'type',
'prefix' => 'prefix',
'options' => 'options',
'database' => 'database',
'alias' => 'alias'
2016-09-07 13:10:03 -04:00
];
2015-07-17 16:01:41 -04:00
foreach($params as $key => $val)
{
if (( ! array_key_exists($key, $skip)) && ! empty($val))
{
2016-09-07 13:10:03 -04:00
$pairs[] = implode('=', [$key, $val]);
}
}
2019-12-11 16:49:06 -05:00
return strtolower($dbType) . ':' . implode(';', $pairs);
}
2016-10-13 21:55:23 -04:00
}