Source of file ConnectionManager.php

Size: 5,137 Bytes - Last Modified: 2018-01-26T14:53:29+00:00

src/ConnectionManager.php

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
Covered by 1 test(s):
  • Query\Tests\ConnectionManagerTest::testNoClone
5455565758596061626364
Covered by 1 test(s):
  • Query\Tests\ConnectionManagerTest::testNoSerialize
6566676869707172737475
Covered by 1 test(s):
  • Query\Tests\ConnectionManagerTest::testNoUnserialize
7677787980818283848586
Covered by 7 test(s):
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testQueryFunctionAlias
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
8788899091
Covered by 7 test(s):
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testQueryFunctionAlias
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
9293949596979899100101102103104
Covered by 6 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testQueryFunctionAlias
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testInvalidConnectionName
105106
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testQueryFunctionAlias
107108
Covered by 4 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testInvalidConnectionName
109110
Covered by 1 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
111112113114
Covered by 3 test(s):
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testInvalidConnectionName
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testInvalidConnectionName
115116117118119120121122123124125126
Covered by 5 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
127128
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
129
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
130131132
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
133134
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
135136137
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
138139
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
140141142143
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
144145146147
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
148149
Covered by 1 test(s):
  • Query\Tests\ConnectionManagerTest::testGetConnection
150151152153
Covered by 1 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
154155156
Covered by 2 test(s):
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
157158159160161162163164165166167168
Covered by 6 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
169
Covered by 6 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
170
Covered by 6 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
171
Covered by 6 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
172173174
Covered by 6 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
175176
Covered by 3 test(s):
  • Query\Tests\Drivers\MySQL\MySQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\PgSQL\PgSQLQueryBuilderTest::testBadDriver
  • Query\Tests\Drivers\SQLite\SQLiteQueryBuilderTest::testBadDriver
177178179180
Covered by 3 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
181182
Covered by 3 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
183184
Covered by 3 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
185186187188
Covered by 3 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
189190
Covered by 3 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
191192193194195196197198
Covered by 3 test(s):
  • Query\Tests\ConnectionManagerTest::testParseParams
  • Query\Tests\ConnectionManagerTest::testConnect
  • Query\Tests\ConnectionManagerTest::testGetConnection
199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
<?php declare(strict_types=1);
/**
 * Query
 *
 * SQL Query Builder / Database Abstraction Layer
 *
 * PHP version 7.1
 *
 * @package     Query
 * @author      Timothy J. Warren <tim@timshomepage.net>
 * @copyright   2012 - 2018 Timothy J. Warren
 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link        https://git.timshomepage.net/aviat4ion/Query
 */
namespace Query;

use DomainException;

/**
 * Connection manager class to manage connections for the
 * Query method
 */
final class ConnectionManager {

	/**
	 * Map of named database connections
	 * @var array
	 */
	private $connections = [];

	/**
	 * Class instance variable
	 * @var ConnectionManager|null
	 */
	private static $instance;

	/**
	 * Private constructor to prevent multiple instances
	 * @codeCoverageIgnore
	 */
	private function __construct()
	{
	}

	/**
	 * Private clone method to prevent cloning
	 *
	 * @throws DomainException
	 * @return void
	 */
	public function __clone()
	{
		throw new DomainException("Can't clone singleton");
	}

	/**
	 * Prevent serialization of this object
	 *
	 * @throws DomainException
	 * @return void
	 */
	public function __sleep()
	{
		throw new DomainException('No serializing of singleton');
	}

	/**
	 * Make sure serialize/deserialize doesn't work
	 *
	 * @throws DomainException
	 * @return void
	 */
	public function __wakeup()
	{
		throw new DomainException("Can't unserialize singleton");
	}

	/**
	 * Return  a connection manager instance
	 *
	 * @staticvar null $instance
	 * @return ConnectionManager
	 */
	public static function getInstance(): ConnectionManager
	{
		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 QueryBuilderInterface
	 * @throws Exception\NonExistentConnectionException
	 */
	public function getConnection($name = ''): QueryBuilderInterface
	{
		// If the parameter is a string, use it as an array index
		if (is_scalar($name) && isset($this->connections[$name]))
		{
			return $this->connections[$name];
		}
		else 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 object|array $params
	 * @throws Exception\BadDBDriverException
	 * @return QueryBuilderInterface
	 */
	public function connect($params): QueryBuilderInterface
	{
		[$dsn, $dbtype, $params, $options] = $this->parseParams($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->setTablePrefix($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 object|array
	 * @throws Exception\BadDBDriverException
	 */
	public function parseParams($params): array
	{
		$params = (object) $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 Exception\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) === 'sqlite')
		{
			$dsn = $params->file;
		}
		else
		{
			$dsn = $this->createDsn($dbtype, $params);
		}


		return [$dsn, $dbtype, $params, $options];
	}

	/**
	 * Create the dsn from the db type and params
	 *
	 * @codeCoverageIgnore
	 * @param string $dbtype
	 * @param array|object $params
	 * @return string
	 */
	private function createDsn(string $dbtype, $params): string
	{
		$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);
	}
}