summaryrefslogtreecommitdiff
path: root/vendor/doctrine/dbal/src/Tools/DsnParser.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/dbal/src/Tools/DsnParser.php')
-rw-r--r--vendor/doctrine/dbal/src/Tools/DsnParser.php217
1 files changed, 217 insertions, 0 deletions
diff --git a/vendor/doctrine/dbal/src/Tools/DsnParser.php b/vendor/doctrine/dbal/src/Tools/DsnParser.php
new file mode 100644
index 0000000..61edc6a
--- /dev/null
+++ b/vendor/doctrine/dbal/src/Tools/DsnParser.php
@@ -0,0 +1,217 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\DBAL\Tools;
6
7use Doctrine\DBAL\Driver;
8use Doctrine\DBAL\DriverManager;
9use Doctrine\DBAL\Exception\MalformedDsnException;
10use SensitiveParameter;
11
12use function array_merge;
13use function assert;
14use function is_a;
15use function is_string;
16use function parse_str;
17use function parse_url;
18use function preg_replace;
19use function rawurldecode;
20use function str_replace;
21use function strpos;
22use function substr;
23
24/** @psalm-import-type Params from DriverManager */
25final class DsnParser
26{
27 /** @param array<string, string|class-string<Driver>> $schemeMapping An array used to map DSN schemes to DBAL drivers */
28 public function __construct(
29 private readonly array $schemeMapping = [],
30 ) {
31 }
32
33 /**
34 * @psalm-return Params
35 *
36 * @throws MalformedDsnException
37 */
38 public function parse(
39 #[SensitiveParameter]
40 string $dsn,
41 ): array {
42 // (pdo-)?sqlite3?:///... => (pdo-)?sqlite3?://localhost/... or else the URL will be invalid
43 $url = preg_replace('#^((?:pdo-)?sqlite3?):///#', '$1://localhost/', $dsn);
44 assert($url !== null);
45
46 $url = parse_url($url);
47
48 if ($url === false) {
49 throw MalformedDsnException::new();
50 }
51
52 foreach ($url as $param => $value) {
53 if (! is_string($value)) {
54 continue;
55 }
56
57 $url[$param] = rawurldecode($value);
58 }
59
60 $params = [];
61
62 if (isset($url['scheme'])) {
63 $params['driver'] = $this->parseDatabaseUrlScheme($url['scheme']);
64 }
65
66 if (isset($url['host'])) {
67 $params['host'] = $url['host'];
68 }
69
70 if (isset($url['port'])) {
71 $params['port'] = $url['port'];
72 }
73
74 if (isset($url['user'])) {
75 $params['user'] = $url['user'];
76 }
77
78 if (isset($url['pass'])) {
79 $params['password'] = $url['pass'];
80 }
81
82 if (isset($params['driver']) && is_a($params['driver'], Driver::class, true)) {
83 $params['driverClass'] = $params['driver'];
84 unset($params['driver']);
85 }
86
87 $params = $this->parseDatabaseUrlPath($url, $params);
88 $params = $this->parseDatabaseUrlQuery($url, $params);
89
90 return $params;
91 }
92
93 /**
94 * Parses the given connection URL and resolves the given connection parameters.
95 *
96 * Assumes that the connection URL scheme is already parsed and resolved into the given connection parameters
97 * via {@see parseDatabaseUrlScheme}.
98 *
99 * @see parseDatabaseUrlScheme
100 *
101 * @param mixed[] $url The URL parts to evaluate.
102 * @param mixed[] $params The connection parameters to resolve.
103 *
104 * @return mixed[] The resolved connection parameters.
105 */
106 private function parseDatabaseUrlPath(array $url, array $params): array
107 {
108 if (! isset($url['path'])) {
109 return $params;
110 }
111
112 $url['path'] = $this->normalizeDatabaseUrlPath($url['path']);
113
114 // If we do not have a known DBAL driver, we do not know any connection URL path semantics to evaluate
115 // and therefore treat the path as a regular DBAL connection URL path.
116 if (! isset($params['driver'])) {
117 return $this->parseRegularDatabaseUrlPath($url, $params);
118 }
119
120 if (strpos($params['driver'], 'sqlite') !== false) {
121 return $this->parseSqliteDatabaseUrlPath($url, $params);
122 }
123
124 return $this->parseRegularDatabaseUrlPath($url, $params);
125 }
126
127 /**
128 * Normalizes the given connection URL path.
129 *
130 * @return string The normalized connection URL path
131 */
132 private function normalizeDatabaseUrlPath(string $urlPath): string
133 {
134 // Trim leading slash from URL path.
135 return substr($urlPath, 1);
136 }
137
138 /**
139 * Parses the query part of the given connection URL and resolves the given connection parameters.
140 *
141 * @param mixed[] $url The connection URL parts to evaluate.
142 * @param mixed[] $params The connection parameters to resolve.
143 *
144 * @return mixed[] The resolved connection parameters.
145 */
146 private function parseDatabaseUrlQuery(array $url, array $params): array
147 {
148 if (! isset($url['query'])) {
149 return $params;
150 }
151
152 $query = [];
153
154 parse_str($url['query'], $query); // simply ingest query as extra params, e.g. charset or sslmode
155
156 return array_merge($params, $query); // parse_str wipes existing array elements
157 }
158
159 /**
160 * Parses the given regular connection URL and resolves the given connection parameters.
161 *
162 * Assumes that the "path" URL part is already normalized via {@see normalizeDatabaseUrlPath}.
163 *
164 * @see normalizeDatabaseUrlPath
165 *
166 * @param mixed[] $url The regular connection URL parts to evaluate.
167 * @param mixed[] $params The connection parameters to resolve.
168 *
169 * @return mixed[] The resolved connection parameters.
170 */
171 private function parseRegularDatabaseUrlPath(array $url, array $params): array
172 {
173 $params['dbname'] = $url['path'];
174
175 return $params;
176 }
177
178 /**
179 * Parses the given SQLite connection URL and resolves the given connection parameters.
180 *
181 * Assumes that the "path" URL part is already normalized via {@see normalizeDatabaseUrlPath}.
182 *
183 * @see normalizeDatabaseUrlPath
184 *
185 * @param mixed[] $url The SQLite connection URL parts to evaluate.
186 * @param mixed[] $params The connection parameters to resolve.
187 *
188 * @return mixed[] The resolved connection parameters.
189 */
190 private function parseSqliteDatabaseUrlPath(array $url, array $params): array
191 {
192 if ($url['path'] === ':memory:') {
193 $params['memory'] = true;
194
195 return $params;
196 }
197
198 $params['path'] = $url['path']; // pdo_sqlite driver uses 'path' instead of 'dbname' key
199
200 return $params;
201 }
202
203 /**
204 * Parses the scheme part from given connection URL and resolves the given connection parameters.
205 *
206 * @return string The resolved driver.
207 */
208 private function parseDatabaseUrlScheme(string $scheme): string
209 {
210 // URL schemes must not contain underscores, but dashes are ok
211 $driver = str_replace('-', '_', $scheme);
212
213 // If the driver is an alias (e.g. "postgres"), map it to the actual name ("pdo-pgsql").
214 // Otherwise, let checkParams decide later if the driver exists.
215 return $this->schemeMapping[$driver] ?? $driver;
216 }
217}