php-censor/src/Database.php

204 lines
4.9 KiB
PHP
Raw Permalink Normal View History

2016-04-12 19:31:39 +02:00
<?php
2018-03-04 09:34:19 +01:00
namespace PHPCensor;
2016-04-12 19:31:39 +02:00
class Database extends \PDO
{
2018-02-28 14:53:21 +01:00
const MYSQL_TYPE = 'mysql';
const POSTGRESQL_TYPE = 'pgsql';
2018-02-28 17:34:07 +01:00
/**
* @var string
*/
protected $type = 'read';
/**
* @var boolean
*/
2016-04-20 12:30:26 +02:00
protected static $initialised = false;
2018-02-28 17:34:07 +01:00
/**
* @var array
*/
protected static $servers = [
'read' => [],
'write' => []
];
/**
* @var array
*/
protected static $connections = [
'read' => null,
'write' => null
];
/**
* @var array
*/
protected static $dsn = [
'read' => '',
'write' => ''
];
protected static $details = [];
2016-04-20 12:30:26 +02:00
/**
* @param string $table
*
* @return string
*/
public function lastInsertIdExtended($table = null)
{
2018-02-28 14:53:21 +01:00
if ($table && self::POSTGRESQL_TYPE === $this->getAttribute(self::ATTR_DRIVER_NAME)) {
return parent::lastInsertId('"' . $table . '_id_seq"');
}
return parent::lastInsertId();
}
2016-04-20 12:30:26 +02:00
protected static function init()
{
$config = Config::getInstance();
2016-04-20 12:30:26 +02:00
$settings = $config->get('b8.database', []);
self::$servers['read'] = $settings['servers']['read'];
2016-04-20 12:30:26 +02:00
self::$servers['write'] = $settings['servers']['write'];
2018-02-28 14:53:21 +01:00
2018-02-28 17:34:07 +01:00
self::$details['driver'] = $settings['type'];
self::$details['db'] = $settings['name'];
self::$details['user'] = $settings['username'];
self::$details['pass'] = $settings['password'];
2017-01-29 03:49:43 +01:00
2016-04-20 12:30:26 +02:00
self::$initialised = true;
}
/**
* @param string $type
*
2018-03-04 09:34:19 +01:00
* @return Database
2017-11-05 15:48:36 +01:00
*
2016-04-20 12:30:26 +02:00
* @throws \Exception
*/
public static function getConnection($type = 'read')
{
if (!self::$initialised) {
self::init();
}
if (is_null(self::$connections[$type])) {
2017-01-29 03:49:43 +01:00
// Shuffle, so we pick a random server:
$servers = self::$servers[$type];
shuffle($servers);
2016-04-20 12:30:26 +02:00
$connection = null;
// Loop until we get a working connection:
while (count($servers)) {
// Pull the next server:
$server = array_shift($servers);
2018-02-28 17:34:07 +01:00
self::$dsn[$type] = self::$details['driver'] . ':host=' . $server['host'];
2017-01-29 03:49:43 +01:00
if (isset($server['port'])) {
2018-02-28 17:34:07 +01:00
self::$dsn[$type] .= ';port=' . (integer)$server['port'];
2016-04-20 12:30:26 +02:00
}
2018-02-28 17:34:07 +01:00
self::$dsn[$type] .= ';dbname=' . self::$details['db'];
2016-04-20 12:30:26 +02:00
$pdoOptions = [
2018-02-28 17:34:07 +01:00
\PDO::ATTR_PERSISTENT => false,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
\PDO::ATTR_TIMEOUT => 2,
];
2018-02-28 17:34:07 +01:00
if (self::MYSQL_TYPE === self::$details['driver']) {
$pdoOptions[\PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES 'UTF8'";
}
2016-04-20 12:30:26 +02:00
// Try to connect:
try {
2017-01-29 03:49:43 +01:00
$connection = new self(
2018-02-28 17:34:07 +01:00
self::$dsn[$type],
2016-04-20 12:30:26 +02:00
self::$details['user'],
self::$details['pass'],
$pdoOptions
2017-01-29 03:49:43 +01:00
);
2018-02-28 17:34:07 +01:00
$connection->setType($type);
2016-04-20 12:30:26 +02:00
} catch (\PDOException $ex) {
$connection = false;
}
// Opened a connection? Break the loop:
if ($connection) {
break;
}
}
// No connection? Oh dear.
if (!$connection && $type === 'read') {
2016-04-20 12:30:26 +02:00
throw new \Exception('Could not connect to any ' . $type . ' servers.');
}
self::$connections[$type] = $connection;
}
return self::$connections[$type];
}
2018-02-28 14:53:21 +01:00
/**
* @return array
*/
2016-04-20 12:30:26 +02:00
public function getDetails()
{
return self::$details;
}
2016-04-12 19:31:39 +02:00
2018-02-28 17:34:07 +01:00
/**
* @return string
*/
public function getDsn()
{
return self::$dsn[$this->type];
}
/**
* @param string $type
*/
public function setType($type)
{
$this->type = $type;
}
2016-04-12 19:31:39 +02:00
public static function reset()
{
2016-04-20 12:30:26 +02:00
self::$connections = ['read' => null, 'write' => null];
2016-04-12 19:31:39 +02:00
self::$initialised = false;
}
2017-01-29 03:49:43 +01:00
2018-02-28 14:53:21 +01:00
/**
* @param string $statement
*
* @return string
*/
protected function quoteNames($statement)
2017-01-29 03:49:43 +01:00
{
$quote = '';
2018-02-28 17:34:07 +01:00
if (self::MYSQL_TYPE === self::$details['driver']) {
2017-01-29 03:49:43 +01:00
$quote = '`';
2018-02-28 17:34:07 +01:00
} elseif (self::POSTGRESQL_TYPE === self::$details['driver']) {
2017-01-29 03:49:43 +01:00
$quote = '"';
}
2018-01-18 15:51:33 +01:00
2018-02-28 14:53:21 +01:00
return preg_replace('/{{(.*?)}}/', ($quote . '\1' . $quote), $statement);
}
2017-01-29 03:49:43 +01:00
2018-02-28 14:53:21 +01:00
/**
* @param string $statement
* @param array $driverOptions
2018-02-28 14:53:21 +01:00
*
* @return \PDOStatement
*/
public function prepareCommon($statement, array $driverOptions = [])
2018-02-28 14:53:21 +01:00
{
return parent::prepare($this->quoteNames($statement), $driverOptions);
2017-01-29 03:49:43 +01:00
}
2016-04-12 19:31:39 +02:00
}