Skip to content

Commit 175e4a1

Browse files
committed
[Messenger] Extract Dsn object
1 parent 7dfc97b commit 175e4a1

12 files changed

+205
-77
lines changed

src/Symfony/Component/Messenger/Transport/AmqpExt/AmqpTransportFactory.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Messenger\Transport\AmqpExt;
1313

14+
use Symfony\Component\Messenger\Transport\Dsn;
1415
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
1516
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
1617
use Symfony\Component\Messenger\Transport\TransportInterface;
@@ -20,13 +21,13 @@
2021
*/
2122
class AmqpTransportFactory implements TransportFactoryInterface
2223
{
23-
public function createTransport(string $dsn, array $options, SerializerInterface $serializer): TransportInterface
24+
public function createTransport(Dsn $dsn, SerializerInterface $serializer): TransportInterface
2425
{
25-
return new AmqpTransport(Connection::fromDsn($dsn, $options), $serializer);
26+
return new AmqpTransport(Connection::fromDsn($dsn), $serializer);
2627
}
2728

28-
public function supports(string $dsn, array $options): bool
29+
public function supports(Dsn $dsn): bool
2930
{
30-
return 0 === strpos($dsn, 'amqp://');
31+
return 'amqp' === $dsn->getScheme();
3132
}
3233
}

src/Symfony/Component/Messenger/Transport/AmqpExt/Connection.php

+14-19
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Messenger\Transport\AmqpExt;
1313

1414
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
15+
use Symfony\Component\Messenger\Transport\Dsn;
1516

1617
/**
1718
* An AMQP connection.
@@ -99,34 +100,28 @@ public function __construct(array $connectionOptions, array $exchangeOptions, ar
99100
*/
100101
public static function fromDsn(string $dsn, array $options = [], AmqpFactory $amqpFactory = null): self
101102
{
102-
if (false === $parsedUrl = parse_url($dsn)) {
103-
// this is a valid URI that parse_url cannot handle when you want to pass all parameters as options
104-
if ('amqp://' !== $dsn) {
105-
throw new InvalidArgumentException(sprintf('The given AMQP DSN "%s" is invalid.', $dsn));
106-
}
107-
108-
$parsedUrl = [];
109-
}
103+
return self::fromDsnObject(Dsn::fromString($dsn, $options));
104+
}
110105

111-
$pathParts = isset($parsedUrl['path']) ? explode('/', trim($parsedUrl['path'], '/')) : [];
112-
$exchangeName = $pathParts[1] ?? 'messages';
113-
parse_str($parsedUrl['query'] ?? '', $parsedQuery);
106+
public static function fromDsnObject(Dsn $dsn, AmqpFactory $amqpFactory = null): self
107+
{
108+
list($vhost, $exchangeName) = ['/', 'messages'] + explode('/', trim($dsn->getPath(''), '/'));
114109

115110
$amqpOptions = array_replace_recursive([
116-
'host' => $parsedUrl['host'] ?? 'localhost',
117-
'port' => $parsedUrl['port'] ?? 5672,
118-
'vhost' => isset($pathParts[0]) ? urldecode($pathParts[0]) : '/',
111+
'host' => $dsn->getHost('localhost'),
112+
'port' => $dsn->getPort(5672),
113+
'vhost' => $vhost,
119114
'exchange' => [
120115
'name' => $exchangeName,
121116
],
122-
], $options, $parsedQuery);
117+
], $dsn->getOptions());
123118

124-
if (isset($parsedUrl['user'])) {
125-
$amqpOptions['login'] = $parsedUrl['user'];
119+
if ($user = $dsn->getUser()) {
120+
$amqpOptions['login'] = $user;
126121
}
127122

128-
if (isset($parsedUrl['pass'])) {
129-
$amqpOptions['password'] = $parsedUrl['pass'];
123+
if ($password = $dsn->getPassword()) {
124+
$amqpOptions['password'] = $password;
130125
}
131126

132127
if (!isset($amqpOptions['queues'])) {

src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php

+9-18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Doctrine\DBAL\Types\Type;
2222
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
2323
use Symfony\Component\Messenger\Exception\TransportException;
24+
use Symfony\Component\Messenger\Transport\Dsn;
2425

2526
/**
2627
* @author Vincent Touzet <vincent.touzet@gmail.com>
@@ -63,34 +64,24 @@ public function getConfiguration(): array
6364
return $this->configuration;
6465
}
6566

66-
public static function buildConfiguration($dsn, array $options = [])
67+
public static function buildConfiguration($dsn, array $options = []): array
6768
{
68-
if (false === $components = parse_url($dsn)) {
69-
throw new InvalidArgumentException(sprintf('The given Doctrine Messenger DSN "%s" is invalid.', $dsn));
70-
}
71-
72-
$query = [];
73-
if (isset($components['query'])) {
74-
parse_str($components['query'], $query);
75-
}
69+
return self::buildConfigurationFromDsnObject(Dsn::fromString($dsn, $options));
70+
}
7671

77-
$configuration = ['connection' => $components['host']];
78-
$configuration += $options + $query + self::DEFAULT_OPTIONS;
72+
public static function buildConfigurationFromDsnObject(Dsn $dsn): array
73+
{
74+
$configuration = ['connection' => $dsn->getHost()];
75+
$options = $dsn->getOptions();
76+
$configuration += $options + self::DEFAULT_OPTIONS;
7977

8078
$configuration['auto_setup'] = filter_var($configuration['auto_setup'], FILTER_VALIDATE_BOOLEAN);
8179

82-
// check for extra keys in options
8380
$optionsExtraKeys = array_diff(array_keys($options), array_keys(self::DEFAULT_OPTIONS));
8481
if (0 < \count($optionsExtraKeys)) {
8582
throw new InvalidArgumentException(sprintf('Unknown option found : [%s]. Allowed options are [%s]', implode(', ', $optionsExtraKeys), implode(', ', self::DEFAULT_OPTIONS)));
8683
}
8784

88-
// check for extra keys in options
89-
$queryExtraKeys = array_diff(array_keys($query), array_keys(self::DEFAULT_OPTIONS));
90-
if (0 < \count($queryExtraKeys)) {
91-
throw new InvalidArgumentException(sprintf('Unknown option found in DSN: [%s]. Allowed options are [%s]', implode(', ', $queryExtraKeys), implode(', ', self::DEFAULT_OPTIONS)));
92-
}
93-
9485
return $configuration;
9586
}
9687

src/Symfony/Component/Messenger/Transport/Doctrine/DoctrineTransportFactory.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Doctrine\Common\Persistence\ConnectionRegistry;
1515
use Symfony\Component\Messenger\Exception\TransportException;
16+
use Symfony\Component\Messenger\Transport\Dsn;
1617
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
1718
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
1819
use Symfony\Component\Messenger\Transport\TransportInterface;
@@ -29,9 +30,9 @@ public function __construct(ConnectionRegistry $registry)
2930
$this->registry = $registry;
3031
}
3132

32-
public function createTransport(string $dsn, array $options, SerializerInterface $serializer): TransportInterface
33+
public function createTransport(Dsn $dsn, SerializerInterface $serializer): TransportInterface
3334
{
34-
$configuration = Connection::buildConfiguration($dsn, $options);
35+
$configuration = Connection::buildConfiguration($dsn);
3536

3637
try {
3738
$driverConnection = $this->registry->getConnection($configuration['connection']);
@@ -44,8 +45,8 @@ public function createTransport(string $dsn, array $options, SerializerInterface
4445
return new DoctrineTransport($connection, $serializer);
4546
}
4647

47-
public function supports(string $dsn, array $options): bool
48+
public function supports(Dsn $dsn): bool
4849
{
49-
return 0 === strpos($dsn, 'doctrine://');
50+
return 'doctrine' === $dsn->getScheme();
5051
}
5152
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Transport;
13+
14+
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Konstantin Myakshin <molodchick@gmail.com>
18+
*/
19+
final class Dsn
20+
{
21+
private $scheme;
22+
private $host;
23+
private $user;
24+
private $password;
25+
private $port;
26+
private $path;
27+
private $options;
28+
29+
public function __construct(string $scheme, string $host, ?string $user = null, ?string $password = null, ?int $port = null, ?string $path = null, array $options = [])
30+
{
31+
$this->scheme = $scheme;
32+
$this->host = $host;
33+
$this->user = $user;
34+
$this->password = $password;
35+
$this->port = $port;
36+
$this->path = $path;
37+
$this->options = $options;
38+
}
39+
40+
public static function fromString(string $dsn, array $options): self
41+
{
42+
if (false === $parsedDsn = parse_url($dsn)) {
43+
throw new InvalidArgumentException(sprintf('The "%s" messenger DSN is invalid.', $dsn));
44+
}
45+
46+
$user = isset($parsedDsn['user']) ? urldecode($parsedDsn['user']) : null;
47+
$password = isset($parsedDsn['pass']) ? urldecode($parsedDsn['pass']) : null;
48+
$port = $parsedDsn['port'] ?? null;
49+
$path = $parsedDsn['path'] ?? null;
50+
parse_str($parsedDsn['query'] ?? '', $options);
51+
52+
return new self($parsedDsn['scheme'], $parsedDsn['host'], $user, $password, $port, $path, $options);
53+
}
54+
55+
public function getScheme(): string
56+
{
57+
return $this->scheme;
58+
}
59+
60+
public function getHost(string $default = null): ?string
61+
{
62+
return $this->host ?? $default;
63+
}
64+
65+
public function getUser(): ?string
66+
{
67+
return $this->user;
68+
}
69+
70+
public function getPassword(): ?string
71+
{
72+
return $this->password;
73+
}
74+
75+
public function getPort(int $default = null): ?int
76+
{
77+
return $this->port ?? $default;
78+
}
79+
80+
public function getPath(string $default = null): ?string
81+
{
82+
return $this->path ?? $default;
83+
}
84+
85+
public function getOption(string $key, $default = null)
86+
{
87+
return $this->options[$key] ?? $default;
88+
}
89+
90+
public function getOptions(): array
91+
{
92+
return $this->options;
93+
}
94+
95+
public function __toString()
96+
{
97+
//FIXME: implement tostring
98+
return '';
99+
}
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Tests\Transport;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Transport\Dsn;
16+
17+
class DsnTest extends TestCase
18+
{
19+
/**
20+
* @dataProvider fromStringProvider
21+
*/
22+
public function testFromString(string $string, Dsn $dsn): void
23+
{
24+
}
25+
26+
/**
27+
* @dataProvider invalidDsnProvider
28+
*/
29+
public function testInvalidDsn(string $dsn, string $exceptionMessage): void
30+
{
31+
}
32+
33+
public function fromStringProvider(): iterable
34+
{
35+
36+
}
37+
38+
public function invalidDsnProvider(): iterable
39+
{
40+
41+
}
42+
}

src/Symfony/Component/Messenger/Transport/InMemoryTransportFactory.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ class InMemoryTransportFactory implements TransportFactoryInterface, ResetInterf
2424
*/
2525
private $createdTransports = [];
2626

27-
public function createTransport(string $dsn, array $options, SerializerInterface $serializer): TransportInterface
27+
public function createTransport(Dsn $dsn, SerializerInterface $serializer): TransportInterface
2828
{
2929
return $this->createdTransports[] = new InMemoryTransport();
3030
}
3131

32-
public function supports(string $dsn, array $options): bool
32+
public function supports(Dsn $dsn): bool
3333
{
34-
return 0 === strpos($dsn, 'in-memory://');
34+
return 'in-memory' === $dsn->getScheme();
3535
}
3636

3737
public function reset()

src/Symfony/Component/Messenger/Transport/RedisExt/Connection.php

+11-15
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
namespace Symfony\Component\Messenger\Transport\RedisExt;
1313

14-
use Symfony\Component\Messenger\Exception\InvalidArgumentException;
1514
use Symfony\Component\Messenger\Exception\LogicException;
1615
use Symfony\Component\Messenger\Exception\TransportException;
16+
use Symfony\Component\Messenger\Transport\Dsn;
1717

1818
/**
1919
* A Redis connection.
@@ -65,25 +65,21 @@ public function __construct(array $configuration, array $connectionCredentials =
6565

6666
public static function fromDsn(string $dsn, array $redisOptions = [], \Redis $redis = null): self
6767
{
68-
if (false === $parsedUrl = parse_url($dsn)) {
69-
throw new InvalidArgumentException(sprintf('The given Redis DSN "%s" is invalid.', $dsn));
70-
}
71-
72-
$pathParts = explode('/', $parsedUrl['path'] ?? '');
68+
return self::fromDsnObject(Dsn::fromString($dsn, $redisOptions));
69+
}
7370

74-
$stream = $pathParts[1] ?? null;
75-
$group = $pathParts[2] ?? null;
76-
$consumer = $pathParts[3] ?? null;
71+
public static function fromDsnObject(Dsn $dsn, \Redis $redis = null): self
72+
{
73+
$pathParts = explode('/', ltrim($dsn->getPath(''), '/'));
74+
list($stream, $group, $consumer) = [null, null, null] + $pathParts;
7775

7876
$connectionCredentials = [
79-
'host' => $parsedUrl['host'] ?? '127.0.0.1',
80-
'port' => $parsedUrl['port'] ?? 6379,
81-
'auth' => $parsedUrl['pass'] ?? $parsedUrl['user'] ?? null,
77+
'host' => $dsn->getHost('127.0.0.1'),
78+
'port' => $dsn->getPort(6379),
79+
'auth' => $dsn->getUser(),
8280
];
8381

84-
if (isset($parsedUrl['query'])) {
85-
parse_str($parsedUrl['query'], $redisOptions);
86-
}
82+
$redisOptions = $dsn->getOptions();
8783

8884
$autoSetup = null;
8985
if (\array_key_exists('auto_setup', $redisOptions)) {

src/Symfony/Component/Messenger/Transport/RedisExt/RedisTransportFactory.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Messenger\Transport\RedisExt;
1313

14+
use Symfony\Component\Messenger\Transport\Dsn;
1415
use Symfony\Component\Messenger\Transport\Serialization\SerializerInterface;
1516
use Symfony\Component\Messenger\Transport\TransportFactoryInterface;
1617
use Symfony\Component\Messenger\Transport\TransportInterface;
@@ -21,13 +22,13 @@
2122
*/
2223
class RedisTransportFactory implements TransportFactoryInterface
2324
{
24-
public function createTransport(string $dsn, array $options, SerializerInterface $serializer): TransportInterface
25+
public function createTransport(Dsn $dsn, SerializerInterface $serializer): TransportInterface
2526
{
26-
return new RedisTransport(Connection::fromDsn($dsn, $options), $serializer);
27+
return new RedisTransport(Connection::fromDsnObject($dsn), $serializer);
2728
}
2829

29-
public function supports(string $dsn, array $options): bool
30+
public function supports(Dsn $dsn): bool
3031
{
31-
return 0 === strpos($dsn, 'redis://');
32+
return 'redis' === $dsn->getScheme();
3233
}
3334
}

0 commit comments

Comments
 (0)