Issues (590)

src/Connection/ConnectionRegistry.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace Bdf\Prime\Connection;
4
5
use Bdf\Dsn\Dsn;
6
use Bdf\Prime\Connection\Configuration\ConfigurationResolver;
7
use Bdf\Prime\Connection\Configuration\ConfigurationResolverInterface;
8
use Bdf\Prime\Connection\Factory\ConnectionFactory;
9
use Bdf\Prime\Connection\Factory\ConnectionFactoryInterface;
10
use Bdf\Prime\ConnectionRegistryInterface;
11
use Bdf\Prime\Exception\DBALException;
12
13
/**
14
 * ConnectionRegistry
15
 */
16
class ConnectionRegistry implements ConnectionRegistryInterface
17
{
18
    /**
19
     * The connection factory
20
     *
21
     * @var ConnectionFactoryInterface
22
     */
23
    private $connectionFactory;
24
25
    /**
26
     * The configuration resolver
27
     *
28
     * @var ConfigurationResolverInterface
29
     */
30
    private $configResolver;
31
32
    /**
33
     * The configuration map
34
     * Contains configuration of some connections
35
     *
36
     * @var array
37
     */
38
    private $parametersMap;
39
40
    /**
41
     * The drive name alias
42
     *
43
     * @var array
44
     */
45
    private static $driverSchemeAliases = [
46
        'db2'        => 'ibm_db2',
47
        'mssql'      => 'pdo_sqlsrv',
48
        'mysql'      => 'pdo_mysql',
49
        'mysql2'     => 'pdo_mysql', // Amazon RDS, for some weird reason
50
        'postgres'   => 'pdo_pgsql',
51
        'postgresql' => 'pdo_pgsql',
52
        'pgsql'      => 'pdo_pgsql',
53
        'sqlite'     => 'pdo_sqlite',
54
        'sqlite3'    => 'pdo_sqlite',
55
    ];
56
57
    /**
58
     * Set default configuration
59
     *
60
     * @param array $parametersMap
61
     * @param ConnectionFactoryInterface|null $connectionFactory
62
     * @param ConfigurationResolverInterface|null $configResolver
63
     */
64 476
    public function __construct(array $parametersMap = [], ConnectionFactoryInterface $connectionFactory = null, ConfigurationResolverInterface $configResolver = null)
65
    {
66 476
        $this->parametersMap = $parametersMap;
67 476
        $this->connectionFactory = $connectionFactory ?? new ConnectionFactory();
68 476
        $this->configResolver = $configResolver ?? new ConfigurationResolver();
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74 404
    public function getConnection(string $name): ConnectionInterface
75
    {
76 404
        return $this->connectionFactory->create($name, $this->getConnectionParameters($name), $this->configResolver->getConfiguration($name));
77
    }
78
79
    /**
80
     * Associate configuration to connection
81
     *
82
     * @param string $connectionName
83
     * @param string|array $parameters
84
     *
85
     * @return void
86
     */
87 59
    public function declareConnection(string $connectionName, $parameters): void
88
    {
89 59
        $this->parametersMap[$connectionName] = $parameters;
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     */
95 5
    public function getConnectionNames(): array
96
    {
97 5
        return array_keys($this->parametersMap);
98
    }
99
100
    /**
101
     * Create the doctrine config for the connection
102
     *
103
     * @param string $connectionName
104
     *
105
     * @return array
106
     */
107 404
    private function getConnectionParameters(string $connectionName): array
108
    {
109 404
        if (!isset($this->parametersMap[$connectionName])) {
110 2
            throw new DBALException('Connection name "' . $connectionName . '" is not set');
111
        }
112
113 402
        $parameters = $this->parametersMap[$connectionName];
114
115
        // Manage string configuration as dsn
116 402
        if (is_string($parameters)) {
117 29
            $parameters = ['url' => $parameters];
118
        }
119
120
        //@todo move in factory ? Allows shard / slave to use url as parameter. Otherwise doctrine will evaluate the url
121
        // Url key describe a dsn. Extract item from dsn and merge info the current config
122 402
        if (isset($parameters['url'])) {
123 32
            $parameters = array_merge($parameters, $this->parseDsn($parameters['url']));
124
            // Remove url: don't let doctrine parse the url
125 32
            unset($parameters['url']);
126
        }
127
128 402
        return $parameters;
129
    }
130
131
    /**
132
     * Parse the dsn string
133
     *
134
     * @param string $dsn
135
     *
136
     * @return array
137
     */
138 32
    private function parseDsn(string $dsn): array
139
    {
140 32
        $request = Dsn::parse($dsn);
141
142 32
        $parameters = $request->getQuery() + [
143 32
                'host' => $request->getHost(),
144 32
                'port' => $request->getPort(),
145 32
                'user' => $request->getUser(),
146 32
                'password' => $request->getPassword(),
147 32
            ];
148
149
        // Get drive from alias or manage synthax 'pdo+mysql' because '_' are not allowed in scheme
150 32
        $parameters['driver'] = self::$driverSchemeAliases[$request->getScheme()] ?? str_replace('+', '_', $request->getScheme());
151
152
        // SQLite option: dont create dbname key use by many drivers
153
        // Sqlite drive needs memory or path key
154
        // Remove the 'path' if not used by sqlite
155 32
        if (strpos($parameters['driver'], 'sqlite') !== false) {
156 26
            if ($request->getPath() === ':memory:') {
157 24
                $parameters['memory'] = true;
158
            } else {
159 26
                $parameters['path'] = $request->getPath();
160
            }
161 6
        } elseif (!isset($parameters['dbname'])) {
162 2
            $parameters['dbname'] = trim($request->getPath(), '/');
0 ignored issues
show
It seems like $request->getPath() can also be of type null; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

162
            $parameters['dbname'] = trim(/** @scrutinizer ignore-type */ $request->getPath(), '/');
Loading history...
163
        }
164
165 32
        return $parameters;
166
    }
167
}
168