1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-08-25 17:41:25 +02:00

[ticket/16643] Add Doctrine DBAL to phpBB

PHPBB3-16643
This commit is contained in:
Máté Bartus
2021-01-16 10:53:46 +01:00
parent d9bfb4d01d
commit aab2679966
17 changed files with 990 additions and 123 deletions

View File

@@ -0,0 +1,114 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\doctrine;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception;
use InvalidArgumentException;
use phpbb\config_php_file;
use phpbb\exception\runtime_exception;
/**
* Doctrine DBAL connection factory.
*/
class connection_factory
{
use driver_convertor;
/**
* Creates a Doctrine DBAL connection from phpBB configuration.
*
* @param config_php_file $config Config PHP file wrapper.
*
* @return Connection Doctrine DBAL connection.
*
* @throws runtime_exception If the database connection could not be established.
* @throws InvalidArgumentException If $driver_name is not a valid phpBB database driver.
*/
public static function get_connection(config_php_file $config) : Connection
{
$driver = $config->get('dbms');
$host = $config->get('dbhost');
$user = $config->get('dbuser');
$pass = $config->get('dbpasswd');
$name = $config->get('dbname');
$port = $config->get('dbport');
return self::get_connection_from_params(
$driver,
$host,
$user,
$pass,
$name,
$port
);
}
/**
* Creates a database connection from the specified parameters.
*
* @param string $driver Driver name.
* @param string $host Hostname.
* @param string|null $user Username.
* @param string|null $password Password.
* @param string|null $name Database name.
* @param string|null $port Database port.
*
* @return Connection Doctrine DBAL connection.
*
* @throws runtime_exception If the database connection could not be established.
* @throws InvalidArgumentException If $driver_name is not a valid phpBB database driver.
*/
public static function get_connection_from_params(
string $driver,
string $host,
?string $user = null,
?string $password = null,
?string $name = null,
?string $port = null) : Connection
{
$available_drivers = DriverManager::getAvailableDrivers();
if (!in_array($driver, $available_drivers))
{
$driver = config_php_file::convert_30_dbms_to_31($driver);
$driver = self::to_doctrine_driver($driver);
}
$params = connection_parameter_factory::get_configuration(
$driver,
$host,
$user,
$password,
$name,
$port
);
try
{
return DriverManager::getConnection($params);
}
catch (Exception $e)
{
throw new runtime_exception('DB_CONNECTION_FAILED');
}
}
/*
* Disable constructor.
*/
private function __construct()
{
}
}

View File

@@ -0,0 +1,180 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\doctrine;
use InvalidArgumentException;
/**
* Helper class to generate Doctrine DBAL configuration.
*/
class connection_parameter_factory
{
/**
* Returns configuration options for Doctrine DBAL.
*
* @param string $driver Driver name.
* @param string $host Hostname.
* @param string|null $user Username.
* @param string|null $password Password.
* @param string|null $name Database name.
* @param string|null $port Database port.
*
* @return array Doctrine DBAL connection parameters.
*
* @throws InvalidArgumentException If a required parameter is empty or null.
*/
public static function get_configuration(
string $driver,
string $host,
?string $user = null,
?string $password = null,
?string $name = null,
?string $port = null) : array
{
$params = [
'driver' => $driver,
];
return self::build_connection_parameters(
$params,
$host,
$user,
$password,
$name,
$port
);
}
/**
* Build Doctrine configuration array.
*
* @param array $params Parameter array.
* @param string $host Database hostname.
* @param string|null $user Username.
* @param string|null $password Password.
* @param string|null $name Database name.
* @param string|null $port Database port.
*
* @return array Doctrine's DBAL configuration for SQLite.
*
* @throws InvalidArgumentException If a required parameter is empty or null.
*/
private static function build_connection_parameters(
array $params,
string $host,
?string $user = null,
?string $password = null,
?string $name = null,
?string $port = null) : array
{
if ($params['driver'] === 'pdo_sqlite')
{
return self::enrich_parameters(
self::build_sqlite_parameters($params, $host, $user, $password)
);
}
if (empty($host) || empty($user) || empty($name))
{
throw new InvalidArgumentException('Required database parameter is not set.');
}
$params = array_merge($params, [
'host' => $host,
'user' => $user,
'dbname' => $name,
]);
if (!empty($password))
{
$params['password'] = $password;
}
if (!empty($port))
{
$params['port'] = (int) $port;
}
return self::enrich_parameters($params);
}
/**
* Build configuration array for SQLite.
*
* @param array $params Parameter array.
* @param string $path Path to the database.
* @param string|null $user Username.
* @param string|null $password Password.
*
* @return array Doctrine's DBAL configuration for SQLite.
*/
private static function build_sqlite_parameters(array $params, string $path, ?string $user, ?string $password) : array
{
$params['path'] = $path;
if (!empty($user))
{
$params['user'] = $user;
}
if (!empty($password))
{
$params['password'] = $password;
}
return $params;
}
/**
* Add additional configuration options to the parameter list.
*
* @param array $params The parameter list to enrich.
*
* @return array The enriched parameter list.
*/
private static function enrich_parameters(array $params) : array
{
$enrichment_tags = [
'pdo_mysql' => [
'charset' => 'UTF8',
],
'oci8' => [
'charset' => 'UTF8',
],
'pdo_pgsql' => [
'charset' => 'UTF8',
],
];
if ($params['driver'] === 'pdo_mysql')
{
$enrichment_tags['pdo_mysql'][\PDO::MYSQL_ATTR_FOUND_ROWS] = true;
}
$driver = $params['driver'];
if (!array_key_exists($driver, $enrichment_tags))
{
return $params;
}
return array_merge($params, $enrichment_tags[$driver]);
}
/*
* Disable constructing this class.
*/
private function __construct()
{
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\doctrine;
use InvalidArgumentException;
/**
* Driver convertor utility for Doctrine DBAL.
*/
trait driver_convertor
{
/**
* Converts phpBB driver names to Doctrine's equivalent.
*
* @param string $driver_name phpBB database driver name.
*
* @return string Doctrine DBAL's driver name.
*
* @throws InvalidArgumentException If $driver_name is not a valid phpBB database driver.
*/
public static function to_doctrine_driver(string $driver_name) : string
{
// Normalize driver name.
$name = str_replace('phpbb\db\driver', '', $driver_name);
$name = preg_replace('/mysql$/i', 'mysqli', $name);
$name = trim($name, '\\');
switch ($name)
{
case 'mssql_odbc':
case 'mssqlnative':
$name = 'pdo_sqlsrv';
break;
case 'mysqli':
$name = 'pdo_mysql';
break;
case 'oracle':
$name = 'oci8';
break;
case 'postgres':
$name = 'pdo_pgsql';
break;
case 'sqlite3':
$name = 'pdo_sqlite';
break;
default:
throw new InvalidArgumentException('Invalid phpBB database driver provided: ' . $driver_name);
}
return $name;
}
}