Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
62.50% |
5 / 8 |
CRAP | |
88.46% |
46 / 52 |
Transport | |
0.00% |
0 / 1 |
|
62.50% |
5 / 8 |
23.81 | |
88.46% |
46 / 52 |
fromDsn | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
fromDsns | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
__construct | |
100.00% |
1 / 1 |
1 | |
100.00% |
2 / 2 |
|||
fromStrings | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
fromString | |
100.00% |
1 / 1 |
2 | |
100.00% |
4 / 4 |
|||
parseDsn | |
0.00% |
0 / 1 |
10.15 | |
88.46% |
23 / 26 |
|||
fromDsnObject | |
0.00% |
0 / 1 |
3.14 | |
75.00% |
3 / 4 |
|||
getDefaultFactories | |
100.00% |
1 / 1 |
3 | |
100.00% |
8 / 8 |
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\Mailer; |
13 | |
14 | use Psr\Log\LoggerInterface; |
15 | use Symfony\Component\Mailer\Bridge\Amazon\Transport\SesTransportFactory; |
16 | use Symfony\Component\Mailer\Bridge\Google\Transport\GmailTransportFactory; |
17 | use Symfony\Component\Mailer\Bridge\Mailchimp\Transport\MandrillTransportFactory; |
18 | use Symfony\Component\Mailer\Bridge\Mailgun\Transport\MailgunTransportFactory; |
19 | use Symfony\Component\Mailer\Bridge\Postmark\Transport\PostmarkTransportFactory; |
20 | use Symfony\Component\Mailer\Bridge\Sendgrid\Transport\SendgridTransportFactory; |
21 | use Symfony\Component\Mailer\Exception\InvalidArgumentException; |
22 | use Symfony\Component\Mailer\Exception\UnsupportedSchemeException; |
23 | use Symfony\Component\Mailer\Transport\Dsn; |
24 | use Symfony\Component\Mailer\Transport\FailoverTransport; |
25 | use Symfony\Component\Mailer\Transport\NullTransportFactory; |
26 | use Symfony\Component\Mailer\Transport\RoundRobinTransport; |
27 | use Symfony\Component\Mailer\Transport\SendmailTransportFactory; |
28 | use Symfony\Component\Mailer\Transport\Smtp\EsmtpTransportFactory; |
29 | use Symfony\Component\Mailer\Transport\TransportFactoryInterface; |
30 | use Symfony\Component\Mailer\Transport\TransportInterface; |
31 | use Symfony\Component\Mailer\Transport\Transports; |
32 | use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; |
33 | use Symfony\Contracts\HttpClient\HttpClientInterface; |
34 | |
35 | /** |
36 | * @author Fabien Potencier <fabien@symfony.com> |
37 | * @author Konstantin Myakshin <molodchick@gmail.com> |
38 | */ |
39 | class Transport |
40 | { |
41 | private const FACTORY_CLASSES = [ |
42 | SesTransportFactory::class, |
43 | GmailTransportFactory::class, |
44 | MandrillTransportFactory::class, |
45 | MailgunTransportFactory::class, |
46 | PostmarkTransportFactory::class, |
47 | SendgridTransportFactory::class, |
48 | ]; |
49 | |
50 | private $factories; |
51 | |
52 | public static function fromDsn(string $dsn, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): TransportInterface |
53 | { |
54 | $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger))); |
55 | |
56 | return $factory->fromString($dsn); |
57 | } |
58 | |
59 | public static function fromDsns(array $dsns, EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): TransportInterface |
60 | { |
61 | $factory = new self(iterator_to_array(self::getDefaultFactories($dispatcher, $client, $logger))); |
62 | |
63 | return $factory->fromStrings($dsns); |
64 | } |
65 | |
66 | /** |
67 | * @param TransportFactoryInterface[] $factories |
68 | */ |
69 | public function __construct(iterable $factories) |
70 | { |
71 | $this->factories = $factories; |
72 | } |
73 | |
74 | public function fromStrings(array $dsns): Transports |
75 | { |
76 | $transports = []; |
77 | foreach ($dsns as $name => $dsn) { |
78 | $transports[$name] = $this->fromString($dsn); |
79 | } |
80 | |
81 | return new Transports($transports); |
82 | } |
83 | |
84 | public function fromString(string $dsn): TransportInterface |
85 | { |
86 | [$transport, $offset] = $this->parseDsn($dsn); |
87 | if ($offset !== \strlen($dsn)) { |
88 | throw new InvalidArgumentException(sprintf('The DSN has some garbage at the end: "%s".', substr($dsn, $offset))); |
89 | } |
90 | |
91 | return $transport; |
92 | } |
93 | |
94 | private function parseDsn(string $dsn, int $offset = 0): array |
95 | { |
96 | static $keywords = [ |
97 | 'failover' => FailoverTransport::class, |
98 | 'roundrobin' => RoundRobinTransport::class, |
99 | ]; |
100 | |
101 | while (true) { |
102 | foreach ($keywords as $name => $class) { |
103 | $name .= '('; |
104 | if ($name === substr($dsn, $offset, \strlen($name))) { |
105 | $offset += \strlen($name) - 1; |
106 | preg_match('{\(([^()]|(?R))*\)}A', $dsn, $matches, 0, $offset); |
107 | if (!isset($matches[0])) { |
108 | continue; |
109 | } |
110 | |
111 | ++$offset; |
112 | $args = []; |
113 | while (true) { |
114 | [$arg, $offset] = $this->parseDsn($dsn, $offset); |
115 | $args[] = $arg; |
116 | if (\strlen($dsn) === $offset) { |
117 | break; |
118 | } |
119 | ++$offset; |
120 | if (')' === $dsn[$offset - 1]) { |
121 | break; |
122 | } |
123 | } |
124 | |
125 | return [new $class($args), $offset]; |
126 | } |
127 | } |
128 | |
129 | if (preg_match('{(\w+)\(}A', $dsn, $matches, 0, $offset)) { |
130 | throw new InvalidArgumentException(sprintf('The "%s" keyword is not valid (valid ones are "%s"), ', $matches[1], implode('", "', array_keys($keywords)))); |
131 | } |
132 | |
133 | if ($pos = strcspn($dsn, ' )', $offset)) { |
134 | return [$this->fromDsnObject(Dsn::fromString(substr($dsn, $offset, $pos))), $offset + $pos]; |
135 | } |
136 | |
137 | return [$this->fromDsnObject(Dsn::fromString(substr($dsn, $offset))), \strlen($dsn)]; |
138 | } |
139 | } |
140 | |
141 | public function fromDsnObject(Dsn $dsn): TransportInterface |
142 | { |
143 | foreach ($this->factories as $factory) { |
144 | if ($factory->supports($dsn)) { |
145 | return $factory->create($dsn); |
146 | } |
147 | } |
148 | |
149 | throw new UnsupportedSchemeException($dsn); |
150 | } |
151 | |
152 | public static function getDefaultFactories(EventDispatcherInterface $dispatcher = null, HttpClientInterface $client = null, LoggerInterface $logger = null): iterable |
153 | { |
154 | foreach (self::FACTORY_CLASSES as $factoryClass) { |
155 | if (class_exists($factoryClass)) { |
156 | yield new $factoryClass($dispatcher, $client, $logger); |
157 | } |
158 | } |
159 | |
160 | yield new NullTransportFactory($dispatcher, $client, $logger); |
161 | |
162 | yield new SendmailTransportFactory($dispatcher, $client, $logger); |
163 | |
164 | yield new EsmtpTransportFactory($dispatcher, $client, $logger); |
165 | } |
166 | } |