Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
73.85% covered (warning)
73.85%
48 / 65
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
connection_factory
73.85% covered (warning)
73.85%
48 / 65
25.00% covered (danger)
25.00%
1 / 4
17.51
0.00% covered (danger)
0.00%
0 / 1
 get_connection
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
1
 get_connection_from_params
75.86% covered (warning)
75.86%
22 / 29
0.00% covered (danger)
0.00%
0 / 1
4.23
 to_doctrine_driver
57.14% covered (warning)
57.14%
12 / 21
0.00% covered (danger)
0.00%
0 / 1
13.04
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 *
4 * This file is part of the phpBB Forum Software package.
5 *
6 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7 * @license GNU General Public License, version 2 (GPL-2.0)
8 *
9 * For full copyright and license information, please see
10 * the docs/CREDITS.txt file.
11 *
12 */
13
14namespace phpbb\db\doctrine;
15
16use Doctrine\DBAL\Configuration;
17use Doctrine\DBAL\Connection;
18use Doctrine\DBAL\DriverManager;
19use Doctrine\DBAL\Exception;
20use Doctrine\DBAL\Types\Type;
21use InvalidArgumentException;
22use phpbb\config_php_file;
23use phpbb\db\middleware\mysql\middleware as mysql_middleware;
24use phpbb\db\middleware\oracle\middleware as oracle_middleware;
25use phpbb\db\middleware\postgresql\middleware as postgresql_middleware;
26use phpbb\db\middleware\sqlsrv\middleware as sqlsrv_middleware;
27use phpbb\exception\runtime_exception;
28
29/**
30 * Doctrine DBAL connection factory.
31 */
32class connection_factory
33{
34    /**
35     * Creates a Doctrine DBAL connection from phpBB configuration.
36     *
37     * @param config_php_file $config Config PHP file wrapper.
38     *
39     * @return Connection Doctrine DBAL connection.
40     *
41     * @throws runtime_exception        If the database connection could not be established.
42     * @throws InvalidArgumentException    If the provided driver name is not a valid phpBB database driver.
43     */
44    public static function get_connection(config_php_file $config): Connection
45    {
46        $driver = $config->get('dbms');
47        $host = $config->get('dbhost');
48        $user = $config->get('dbuser');
49        $pass = $config->get('dbpasswd');
50        $name = $config->get('dbname');
51        $port = $config->get('dbport');
52
53        return self::get_connection_from_params(
54            $driver,
55            $host,
56            $user,
57            $pass,
58            $name,
59            $port
60        );
61    }
62
63    /**
64     * Creates a database connection from the specified parameters.
65     *
66     * @param string      $driver   Driver name.
67     * @param string      $host     Hostname.
68     * @param string|null $user     Username.
69     * @param string|null $password Password.
70     * @param string|null $name     Database name.
71     * @param string|null $port     Database port.
72     *
73     * @return Connection Doctrine DBAL connection.
74     *
75     * @throws runtime_exception        If the database connection could not be established.
76     * @throws InvalidArgumentException    If $driver is not a valid phpBB database driver.
77     */
78    public static function get_connection_from_params(
79        string $driver,
80        string $host,
81        string|null $user = null,
82        string|null $password = null,
83        string|null $name = null,
84        string|null $port = null): Connection
85    {
86        $available_drivers = DriverManager::getAvailableDrivers();
87        if (!in_array($driver, $available_drivers))
88        {
89            $driver = config_php_file::convert_30_dbms_to_31($driver);
90            $driver = self::to_doctrine_driver($driver);
91        }
92
93        $params = connection_parameter_factory::get_configuration(
94            $driver,
95            $host,
96            $user,
97            $password,
98            $name,
99            $port
100        );
101
102        $middleware = match($driver)
103        {
104            'pdo_mysql', 'mysqli'    => [new mysql_middleware()],
105            'pdo_oci', 'oci8'        => [new oracle_middleware()],
106            'pdo_pgsql', 'pgsql'    => [new postgresql_middleware()],
107            'pdo_sqlsrv', 'sqlsrv'    => [new sqlsrv_middleware()],
108            default    => [],
109        };
110
111        try
112        {
113            $connection_config = new Configuration();
114            $connection_config->setMiddlewares($middleware);
115
116            $connection = DriverManager::getConnection($params, $connection_config);
117            if (!Type::hasType(case_insensitive_string::CASE_INSENSITIVE_STRING))
118            {
119                Type::addType(case_insensitive_string::CASE_INSENSITIVE_STRING, case_insensitive_string::class);
120            }
121            $connection->getDatabasePlatform()->registerDoctrineTypeMapping('varchar_ci', case_insensitive_string::CASE_INSENSITIVE_STRING);
122            return $connection;
123        }
124        catch (Exception $e)
125        {
126            throw new runtime_exception('DB_CONNECTION_FAILED', [], $e);
127        }
128    }
129
130    /**
131     * Converts phpBB driver names to Doctrine's equivalent.
132     *
133     * @param string $driver_name phpBB database driver name.
134     *
135     * @return string Doctrine DBAL's driver name.
136     *
137     * @throws InvalidArgumentException If $driver_name is not a valid phpBB database driver.
138     */
139    private static function to_doctrine_driver(string $driver_name): string
140    {
141        // Normalize driver name.
142        $name = str_replace('phpbb\db\driver', '', $driver_name);
143        $name = preg_replace('/mysql$/i', 'mysqli', $name);
144        $name = trim($name, '\\');
145
146        switch ($name)
147        {
148            case 'mssql_odbc':
149            case 'mssqlnative':
150                $name = 'pdo_sqlsrv';
151            break;
152
153            case 'mysqli':
154                $name = 'pdo_mysql';
155            break;
156
157            case 'oracle':
158                $name = 'oci8';
159            break;
160
161            case 'postgres':
162                $name = 'pdo_pgsql';
163            break;
164
165            case 'sqlite3':
166                $name = 'pdo_sqlite';
167            break;
168
169            default:
170                throw new InvalidArgumentException('Invalid phpBB database driver provided: ' . $driver_name);
171        }
172
173        return $name;
174    }
175
176    /*
177     * Disable constructor.
178     */
179    private function __construct()
180    {
181    }
182}