Skip to content

Commit 36df270

Browse files
committed
Introduce DbUrlParser #10
1 parent 094a9ec commit 36df270

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WpTestsStarter\Exception;
6+
7+
class RuntimeException extends \RuntimeException implements \Throwable
8+
{
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WpTestsStarter\Exception;
6+
7+
interface Throwable extends \Throwable
8+
{
9+
}
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WpTestsStarter\Helper;
6+
7+
use WpTestsStarter\Exception\RuntimeException;
8+
9+
class DbUrlParser
10+
{
11+
12+
/**
13+
* Parses a URL like mysql://user:password@host/database?table_prefix=wp_&charset=utf8mb4
14+
* all parts are optional
15+
*
16+
* @return array{
17+
* host: ?string,
18+
* user: ?string,
19+
* password: ?string,
20+
* db: ?string,
21+
* table_prefix: ?string,
22+
* charset: ?string
23+
* }
24+
*/
25+
public function parse(string $dbUrl): array
26+
{
27+
$credentials = [
28+
'host' => null,
29+
'user' => null,
30+
'password' => null,
31+
'db' => null,
32+
'table_prefix' => null,
33+
'charset' => null,
34+
];
35+
36+
$parts = parse_url($dbUrl);
37+
if (! is_array($parts)) {
38+
throw new RuntimeException("Please provide a valid dbUrl");
39+
}
40+
41+
if (array_key_exists('scheme', $parts) && $parts['scheme'] !== 'mysql') {
42+
throw new RuntimeException("Currently only 'mysql' databases are supported");
43+
}
44+
45+
array_key_exists('host', $parts) and $credentials['host'] = $parts['host'];
46+
array_key_exists('user', $parts) and $credentials['user'] = $parts['user'];
47+
array_key_exists('pass', $parts) and $credentials['password'] = $parts['pass'];
48+
array_key_exists('path', $parts) and $credentials['db'] = trim($parts['path'], '/');
49+
50+
if (! array_key_exists('query', $parts) || empty($parts['query'])) {
51+
return $credentials;
52+
}
53+
54+
$query = [];
55+
parse_str($parts['query'], $query);
56+
57+
array_key_exists('table_prefix', $query) and $credentials['table_prefix'] = $query['table_prefix'];
58+
array_key_exists('charset', $query) and $credentials['charset'] = $query['charset'];
59+
60+
return $credentials;
61+
}
62+
}

tests/Unit/Helper/DbUrlParserTest.php

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace WpTestsStarter\Test\Unit\Helper;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use WpTestsStarter\Exception\RuntimeException;
9+
use WpTestsStarter\Helper\DbUrlParser;
10+
11+
12+
class DbUrlParserTest extends TestCase
13+
{
14+
15+
/**
16+
* @dataProvider parseData
17+
*/
18+
public function testParse(string $dbUrl, array $expected): void
19+
{
20+
self::assertEquals(
21+
$expected,
22+
(new DbUrlParser())->parse($dbUrl)
23+
);
24+
}
25+
26+
/**
27+
* @see testParse
28+
*/
29+
public function parseData(): iterable
30+
{
31+
32+
yield 'Test entire parameter set' => [
33+
'dbUrl' => 'mysql://john:T0p3ecr3t@localhost/wordpress?table_prefix=wp_tests_&charset=iso88591',
34+
'expected' => [
35+
'user' => 'john',
36+
'host' => 'localhost',
37+
'password' => 'T0p3ecr3t',
38+
'db' => 'wordpress',
39+
'table_prefix' => 'wp_tests_',
40+
'charset' => 'iso88591',
41+
]
42+
];
43+
44+
yield 'Only user and host' => [
45+
'dbUrl' => 'mysql://john@localhost',
46+
'expected' => [
47+
'user' => 'john',
48+
'host' => 'localhost',
49+
'password' => null,
50+
'db' => null,
51+
'table_prefix' => null,
52+
'charset' => null,
53+
]
54+
];
55+
56+
yield 'Nothing at all' => [
57+
'dbUrl' => 'mysql:',
58+
'expected' => [
59+
'user' => null,
60+
'host' => null,
61+
'password' => null,
62+
'db' => null,
63+
'table_prefix' => null,
64+
'charset' => null,
65+
]
66+
];
67+
}
68+
69+
/**
70+
* @dataProvider parseThrowsExceptionData
71+
*/
72+
public function testParseThrowsException(string $url, string $expectedMessage): void
73+
{
74+
$testee = new DbUrlParser();
75+
76+
self::expectException(RuntimeException::class);
77+
self::expectExceptionMessage($expectedMessage);
78+
79+
$testee->parse($url);
80+
}
81+
82+
/**
83+
* @see testParseThrowsException
84+
*/
85+
public function parseThrowsExceptionData(): iterable
86+
{
87+
88+
yield 'Test invalid URL' => [
89+
'mysql://',
90+
"Please provide a valid dbUrl",
91+
];
92+
93+
yield 'Test unsupported scheme' => [
94+
'mssql:',
95+
"Currently only 'mysql' databases are supported",
96+
];
97+
}
98+
}

0 commit comments

Comments
 (0)