diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php
index 85cbe17b71..5d564774a7 100644
--- a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillAssertTrait.php
@@ -17,7 +17,7 @@ use PHPUnit\Framework\Constraint\StringContains;
use PHPUnit\Framework\Constraint\TraversableContains;
/**
- * @internal
+ * This trait is @internal
*/
trait PolyfillAssertTrait
{
diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php
index 071a719488..69609c5ea4 100644
--- a/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/PolyfillTestCaseTrait.php
@@ -15,7 +15,7 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
/**
- * @internal
+ * This trait is @internal
*/
trait PolyfillTestCaseTrait
{
diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php
index 50c805228b..dc3e83b776 100644
--- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php
+++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php
@@ -156,12 +156,6 @@ if (!file_exists("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit") || $configurationH
$alteredCode = preg_replace('/abstract class (?:Assert|PHPUnit_Framework_Assert)[^\{]+\{/', '$0 '.PHP_EOL." use \Symfony\Bridge\PhpUnit\Legacy\PolyfillAssertTrait;", $alteredCode, 1);
file_put_contents($alteredFile, $alteredCode);
- // remove internal annotation from polyfill
- foreach (array('PolyfillTestCaseTrait', 'PolyfillAssertTrait') as $polyfill) {
- $traitFile = "./vendor/symfony/phpunit-bridge/Legacy/$polyfill.php";
- file_put_contents($traitFile, str_replace(' * @internal', '', file_get_contents($traitFile)));
- }
-
file_put_contents('phpunit', <<<'EOPHP'
end()
->booleanNode('logging')->defaultValue(false)->end()
->scalarNode('formatter')->defaultValue('translator.formatter.default')->end()
+ ->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end()
->scalarNode('default_path')
->info('The default path used to load translations')
->defaultValue('%kernel.project_dir%/translations')
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 22da4b579c..19721fb871 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -992,6 +992,10 @@ class FrameworkExtension extends Extension
$translator = $container->findDefinition('translator.default');
$translator->addMethodCall('setFallbackLocales', [$config['fallbacks'] ?: [$defaultLocale]]);
+ $defaultOptions = $translator->getArgument(4);
+ $defaultOptions['cache_dir'] = $config['cache_dir'];
+ $translator->setArgument(4, $defaultOptions);
+
$container->setParameter('translator.logging', $config['logging']);
$container->setParameter('translator.default_path', $config['default_path']);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index 89534ea5b6..24de7dd28f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -173,6 +173,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
index 9bdd9c0d7e..4bc417ac91 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
@@ -225,6 +225,7 @@ class ConfigurationTest extends TestCase
'translator' => [
'enabled' => !class_exists(FullStack::class),
'fallbacks' => [],
+ 'cache_dir' => '%kernel.cache_dir%/translations',
'logging' => false,
'formatter' => 'translator.formatter.default',
'paths' => [],
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
index e02ba9183f..4ba1c44a63 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -46,6 +46,7 @@ $container->loadFromExtension('framework', [
'enabled' => true,
'fallback' => 'fr',
'paths' => ['%kernel.project_dir%/Fixtures/translations'],
+ 'cache_dir' => '%kernel.cache_dir%/translations',
],
'validation' => [
'enabled' => true,
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php
new file mode 100644
index 0000000000..6f2568ffd5
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/translator_cache_dir_disabled.php
@@ -0,0 +1,7 @@
+loadFromExtension('framework', [
+ 'translator' => [
+ 'cache_dir' => null,
+ ],
+]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
index 905c187ef8..9f619b505d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -26,7 +26,7 @@
-
+
%kernel.project_dir%/Fixtures/translations
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml
new file mode 100644
index 0000000000..5704ff7cd7
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/translator_cache_dir_disabled.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
index 9194911b06..e3eb8f60bc 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
@@ -36,6 +36,7 @@ framework:
enabled: true
fallback: fr
default_path: '%kernel.project_dir%/translations'
+ cache_dir: '%kernel.cache_dir%/translations'
paths: ['%kernel.project_dir%/Fixtures/translations']
validation:
enabled: true
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml
new file mode 100644
index 0000000000..6ad1c7330f
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/translator_cache_dir_disabled.yml
@@ -0,0 +1,3 @@
+framework:
+ translator:
+ cache_dir: ~
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index a0a709c032..8c1ef9d145 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -54,6 +54,7 @@ use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
use Symfony\Component\Workflow;
+use Symfony\Contracts\Translation\TranslatorInterface;
abstract class FrameworkExtensionTest extends TestCase
{
@@ -683,6 +684,9 @@ abstract class FrameworkExtensionTest extends TestCase
$this->assertEquals('translator.default', (string) $container->getAlias('translator'), '->registerTranslatorConfiguration() redefines translator service from identity to real translator');
$options = $container->getDefinition('translator.default')->getArgument(4);
+ $this->assertArrayHasKey('cache_dir', $options);
+ $this->assertSame($container->getParameter('kernel.cache_dir').'/translations', $options['cache_dir']);
+
$files = array_map('realpath', $options['resource_files']['en']);
$ref = new \ReflectionClass('Symfony\Component\Validator\Validation');
$this->assertContains(
@@ -739,6 +743,13 @@ abstract class FrameworkExtensionTest extends TestCase
$this->assertEquals(['en', 'fr'], $calls[1][1][0]);
}
+ public function testTranslatorCacheDirDisabled()
+ {
+ $container = $this->createContainerFromFile('translator_cache_dir_disabled');
+ $options = $container->getDefinition('translator.default')->getArgument(4);
+ $this->assertNull($options['cache_dir']);
+ }
+
public function testValidation()
{
$container = $this->createContainerFromFile('full');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php
index 4b74aa8274..9855a0ded4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/MailerTest.php
@@ -42,6 +42,11 @@ class MailerTest extends AbstractWebTestCase
$this->onDoSend = $onDoSend;
}
+ public function getName(): string
+ {
+ return 'dummy://local';
+ }
+
protected function doSend(SentMessage $message): void
{
$onDoSend = $this->onDoSend;
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index acd54e826e..f68e0950b3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -73,6 +73,7 @@
"symfony/dom-crawler": "<4.4",
"symfony/form": "<4.4",
"symfony/lock": "<4.4",
+ "symfony/mailer": "<4.4",
"symfony/messenger": "<4.4",
"symfony/property-info": "<4.4",
"symfony/serializer": "<4.4",
diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php
index e3710f0632..5305540b39 100644
--- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesApiTransport.php
@@ -43,6 +43,11 @@ class SesApiTransport extends AbstractApiTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('api://%s@ses?region=%s', $this->accessKey, $this->region);
+ }
+
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
{
$date = gmdate('D, d M Y H:i:s e');
diff --git a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php
index 43482567ca..e93511fdde 100644
--- a/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Amazon/Transport/SesHttpTransport.php
@@ -42,6 +42,11 @@ class SesHttpTransport extends AbstractHttpTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('http://%s@ses?region=%s', $this->accessKey, $this->region);
+ }
+
protected function doSendHttp(SentMessage $message): ResponseInterface
{
$date = gmdate('D, d M Y H:i:s e');
diff --git a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php
index d4be46d5ab..9b1748904c 100644
--- a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillApiTransport.php
@@ -36,6 +36,11 @@ class MandrillApiTransport extends AbstractApiTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('api://mandrill');
+ }
+
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
{
$response = $this->client->request('POST', self::ENDPOINT, [
diff --git a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php
index 10ef9046e6..e850ba0cb8 100644
--- a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php
@@ -34,6 +34,11 @@ class MandrillHttpTransport extends AbstractHttpTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('http://mandrill');
+ }
+
protected function doSendHttp(SentMessage $message): ResponseInterface
{
$envelope = $message->getEnvelope();
diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php
index 0a1872146b..d55e498bea 100644
--- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunApiTransport.php
@@ -41,6 +41,11 @@ class MailgunApiTransport extends AbstractApiTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('api://%s@mailgun?region=%s', $this->domain, $this->region);
+ }
+
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
{
$body = new FormDataPart($this->getPayload($email, $envelope));
diff --git a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php
index df98218407..bda648232d 100644
--- a/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Mailgun/Transport/MailgunHttpTransport.php
@@ -40,6 +40,11 @@ class MailgunHttpTransport extends AbstractHttpTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('http://%s@mailgun?region=%s', $this->domain, $this->region);
+ }
+
protected function doSendHttp(SentMessage $message): ResponseInterface
{
$body = new FormDataPart([
diff --git a/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php
index 07a45fb0cc..b2abd43a84 100644
--- a/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Postmark/Transport/PostmarkApiTransport.php
@@ -36,6 +36,11 @@ class PostmarkApiTransport extends AbstractApiTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('api://postmark');
+ }
+
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
{
$response = $this->client->request('POST', self::ENDPOINT, [
diff --git a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php
index 94b657e398..0da12690fd 100644
--- a/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Sendgrid/Transport/SendgridApiTransport.php
@@ -37,6 +37,11 @@ class SendgridApiTransport extends AbstractApiTransport
parent::__construct($client, $dispatcher, $logger);
}
+ public function getName(): string
+ {
+ return sprintf('api://sendgrid');
+ }
+
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
{
$response = $this->client->request('POST', self::ENDPOINT, [
diff --git a/src/Symfony/Component/Mailer/CHANGELOG.md b/src/Symfony/Component/Mailer/CHANGELOG.md
index 7e7e758dac..6a0669faca 100644
--- a/src/Symfony/Component/Mailer/CHANGELOG.md
+++ b/src/Symfony/Component/Mailer/CHANGELOG.md
@@ -4,12 +4,14 @@ CHANGELOG
4.4.0
-----
+ * [BC BREAK] `TransportInterface` has a new `getName()` method
* [BC BREAK] Classes `AbstractApiTransport` and `AbstractHttpTransport` moved under `Transport` sub-namespace.
* [BC BREAK] Transports depend on `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`
instead of `Symfony\Component\EventDispatcher\EventDispatcherInterface`.
* Added possibility to register custom transport for dsn by implementing
`Symfony\Component\Mailer\Transport\TransportFactoryInterface` and tagging with `mailer.transport_factory` tag in DI.
* Added `Symfony\Component\Mailer\Test\TransportFactoryTestCase` to ease testing custom transport factories.
+ * Added `SentMessage::getDebug()` and `TransportExceptionInterface::getDebug` to help debugging
4.3.0
-----
diff --git a/src/Symfony/Component/Mailer/Test/TransportFactoryTestCase.php b/src/Symfony/Component/Mailer/Test/TransportFactoryTestCase.php
index e9c3c5d0f1..0fee7d3b9a 100644
--- a/src/Symfony/Component/Mailer/Test/TransportFactoryTestCase.php
+++ b/src/Symfony/Component/Mailer/Test/TransportFactoryTestCase.php
@@ -69,6 +69,9 @@ abstract class TransportFactoryTestCase extends TestCase
$factory = $this->getFactory();
$this->assertEquals($transport, $factory->create($dsn));
+ if ('smtp' !== $dsn->getScheme()) {
+ $this->assertStringMatchesFormat($dsn->getScheme().'://%S'.$dsn->getHost().'%S', $transport->getName());
+ }
}
/**
diff --git a/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php
index 9243263fdd..5677ecab2c 100644
--- a/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php
+++ b/src/Symfony/Component/Mailer/Tests/Transport/FailoverTransportTest.php
@@ -29,6 +29,16 @@ class FailoverTransportTest extends TestCase
new FailoverTransport([]);
}
+ public function testGetName()
+ {
+ $t1 = $this->createMock(TransportInterface::class);
+ $t1->expects($this->once())->method('getName')->willReturn('t1://local');
+ $t2 = $this->createMock(TransportInterface::class);
+ $t2->expects($this->once())->method('getName')->willReturn('t2://local');
+ $t = new FailoverTransport([$t1, $t2]);
+ $this->assertEquals('t1://local || t2://local', $t->getName());
+ }
+
public function testSendFirstWork()
{
$t1 = $this->createMock(TransportInterface::class);
diff --git a/src/Symfony/Component/Mailer/Tests/Transport/NullTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/NullTransportTest.php
new file mode 100644
index 0000000000..7a25994bf8
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Tests/Transport/NullTransportTest.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Mailer\Tests\Transport;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Mailer\Transport\NullTransport;
+
+class NullTransportTest extends TestCase
+{
+ public function testName()
+ {
+ $t = new NullTransport();
+ $this->assertEquals('smtp://null', $t->getName());
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php
index 4b2316da5d..f130f6d3fb 100644
--- a/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php
+++ b/src/Symfony/Component/Mailer/Tests/Transport/RoundRobinTransportTest.php
@@ -28,6 +28,16 @@ class RoundRobinTransportTest extends TestCase
new RoundRobinTransport([]);
}
+ public function testGetName()
+ {
+ $t1 = $this->createMock(TransportInterface::class);
+ $t1->expects($this->once())->method('getName')->willReturn('t1://local');
+ $t2 = $this->createMock(TransportInterface::class);
+ $t2->expects($this->once())->method('getName')->willReturn('t2://local');
+ $t = new RoundRobinTransport([$t1, $t2]);
+ $this->assertEquals('t1://local && t2://local', $t->getName());
+ }
+
public function testSendAlternate()
{
$t1 = $this->createMock(TransportInterface::class);
diff --git a/src/Symfony/Component/Mailer/Tests/Transport/SendmailTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/SendmailTransportTest.php
new file mode 100644
index 0000000000..2f79c0ff52
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Tests/Transport/SendmailTransportTest.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Mailer\Tests\Transport;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Mailer\Transport\SendmailTransport;
+
+class SendmailTransportTest extends TestCase
+{
+ public function testName()
+ {
+ $t = new SendmailTransport();
+ $this->assertEquals('smtp://sendmail', $t->getName());
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php
new file mode 100644
index 0000000000..27494e1506
--- /dev/null
+++ b/src/Symfony/Component/Mailer/Tests/Transport/Smtp/SmtpTransportTest.php
@@ -0,0 +1,28 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Mailer\Tests\Transport\Smtp;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Mailer\Transport\Smtp\SmtpTransport;
+use Symfony\Component\Mailer\Transport\Smtp\Stream\SocketStream;
+
+class SmtpTransportTest extends TestCase
+{
+ public function testName()
+ {
+ $t = new SmtpTransport();
+ $this->assertEquals('smtp://localhost:25', $t->getName());
+
+ $t = new SmtpTransport((new SocketStream())->setHost('127.0.0.1')->setPort(2525));
+ $this->assertEquals('smtp://127.0.0.1:2525', $t->getName());
+ }
+}
diff --git a/src/Symfony/Component/Mailer/Tests/TransportTest.php b/src/Symfony/Component/Mailer/Tests/TransportTest.php
index d5a053ed27..139b644875 100644
--- a/src/Symfony/Component/Mailer/Tests/TransportTest.php
+++ b/src/Symfony/Component/Mailer/Tests/TransportTest.php
@@ -68,6 +68,11 @@ class DummyTransport implements Transport\TransportInterface
{
throw new \BadMethodCallException('This method newer should be called.');
}
+
+ public function getName(): string
+ {
+ return sprintf('dummy://local');
+ }
}
class DummyTransportFactory implements Transport\TransportFactoryInterface
diff --git a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php
index 735278320d..3dd59c195c 100644
--- a/src/Symfony/Component/Mailer/Transport/AbstractTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/AbstractTransport.php
@@ -39,6 +39,8 @@ abstract class AbstractTransport implements TransportInterface
$this->logger = $logger ?: new NullLogger();
}
+ abstract public function getName(): string;
+
/**
* Sets the maximum number of messages to send per second (0 to disable).
*/
diff --git a/src/Symfony/Component/Mailer/Transport/FailoverTransport.php b/src/Symfony/Component/Mailer/Transport/FailoverTransport.php
index 29ac421692..8722aa4be0 100644
--- a/src/Symfony/Component/Mailer/Transport/FailoverTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/FailoverTransport.php
@@ -28,4 +28,9 @@ class FailoverTransport extends RoundRobinTransport
return $this->currentTransport;
}
+
+ protected function getNameSymbol(): string
+ {
+ return '||';
+ }
}
diff --git a/src/Symfony/Component/Mailer/Transport/NullTransport.php b/src/Symfony/Component/Mailer/Transport/NullTransport.php
index b1daee3b9d..96df22cc6d 100644
--- a/src/Symfony/Component/Mailer/Transport/NullTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/NullTransport.php
@@ -23,4 +23,9 @@ final class NullTransport extends AbstractTransport
protected function doSend(SentMessage $message): void
{
}
+
+ public function getName(): string
+ {
+ return 'smtp://null';
+ }
}
diff --git a/src/Symfony/Component/Mailer/Transport/RoundRobinTransport.php b/src/Symfony/Component/Mailer/Transport/RoundRobinTransport.php
index c5fefd2718..261c38f46f 100644
--- a/src/Symfony/Component/Mailer/Transport/RoundRobinTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/RoundRobinTransport.php
@@ -56,6 +56,13 @@ class RoundRobinTransport implements TransportInterface
throw new TransportException('All transports failed.');
}
+ public function getName(): string
+ {
+ return implode(' '.$this->getNameSymbol().' ', array_map(function (TransportInterface $transport) {
+ return $transport->getName();
+ }, $this->transports));
+ }
+
/**
* Rotates the transport list around and returns the first instance.
*/
@@ -90,6 +97,11 @@ class RoundRobinTransport implements TransportInterface
return $this->deadTransports->contains($transport);
}
+ protected function getNameSymbol(): string
+ {
+ return '&&';
+ }
+
private function moveCursor(int $cursor): int
{
return ++$cursor >= \count($this->transports) ? 0 : $cursor;
diff --git a/src/Symfony/Component/Mailer/Transport/SendmailTransport.php b/src/Symfony/Component/Mailer/Transport/SendmailTransport.php
index 4494c55610..db57221750 100644
--- a/src/Symfony/Component/Mailer/Transport/SendmailTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/SendmailTransport.php
@@ -73,6 +73,11 @@ class SendmailTransport extends AbstractTransport
return parent::send($message, $envelope);
}
+ public function getName(): string
+ {
+ return $this->transport->getName();
+ }
+
protected function doSend(SentMessage $message): void
{
$this->getLogger()->debug(sprintf('Email transport "%s" starting', __CLASS__));
diff --git a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php
index 34e4cc9f3e..f50e670848 100644
--- a/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php
+++ b/src/Symfony/Component/Mailer/Transport/Smtp/SmtpTransport.php
@@ -126,6 +126,15 @@ class SmtpTransport extends AbstractTransport
return $message;
}
+ public function getName(): string
+ {
+ if ($this->stream instanceof SocketStream) {
+ return sprintf('smtp://%s:%d', $this->stream->getHost(), $this->stream->getPort());
+ }
+
+ return sprintf('smtp://sendmail');
+ }
+
/**
* Runs a command against the stream, expecting the given response codes.
*
diff --git a/src/Symfony/Component/Mailer/Transport/TransportInterface.php b/src/Symfony/Component/Mailer/Transport/TransportInterface.php
index 29ab4d3dc5..cc30f65f47 100644
--- a/src/Symfony/Component/Mailer/Transport/TransportInterface.php
+++ b/src/Symfony/Component/Mailer/Transport/TransportInterface.php
@@ -30,4 +30,6 @@ interface TransportInterface
* @throws TransportExceptionInterface
*/
public function send(RawMessage $message, SmtpEnvelope $envelope = null): ?SentMessage;
+
+ public function getName(): string;
}
diff --git a/src/Symfony/Component/Mime/CHANGELOG.md b/src/Symfony/Component/Mime/CHANGELOG.md
index 796cfdd155..0b252bd1d3 100644
--- a/src/Symfony/Component/Mime/CHANGELOG.md
+++ b/src/Symfony/Component/Mime/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+4.4.0
+-----
+
+ * Added `AbstractPart::asDebugString()`
+
4.3.3
-----
diff --git a/src/Symfony/Component/Mime/Part/AbstractMultipartPart.php b/src/Symfony/Component/Mime/Part/AbstractMultipartPart.php
index 76f58128c1..48b8620232 100644
--- a/src/Symfony/Component/Mime/Part/AbstractMultipartPart.php
+++ b/src/Symfony/Component/Mime/Part/AbstractMultipartPart.php
@@ -74,6 +74,20 @@ abstract class AbstractMultipartPart extends AbstractPart
yield '--'.$this->getBoundary()."--\r\n";
}
+ public function asDebugString(): string
+ {
+ $str = parent::asDebugString();
+ foreach ($this->getParts() as $part) {
+ $lines = explode("\n", $part->asDebugString());
+ $str .= "\n └ ".array_shift($lines);
+ foreach ($lines as $line) {
+ $str .= "\n |".$line;
+ }
+ }
+
+ return $str;
+ }
+
private function getBoundary(): string
{
if (null === $this->boundary) {
diff --git a/src/Symfony/Component/Mime/Part/AbstractPart.php b/src/Symfony/Component/Mime/Part/AbstractPart.php
index c9df1050a3..93892d9df6 100644
--- a/src/Symfony/Component/Mime/Part/AbstractPart.php
+++ b/src/Symfony/Component/Mime/Part/AbstractPart.php
@@ -50,6 +50,11 @@ abstract class AbstractPart
yield from $this->bodyToIterable();
}
+ public function asDebugString(): string
+ {
+ return $this->getMediaType().'/'.$this->getMediaSubtype();
+ }
+
abstract public function bodyToString(): string;
abstract public function bodyToIterable(): iterable;
diff --git a/src/Symfony/Component/Mime/Part/DataPart.php b/src/Symfony/Component/Mime/Part/DataPart.php
index e8436712ca..128c53eb62 100644
--- a/src/Symfony/Component/Mime/Part/DataPart.php
+++ b/src/Symfony/Component/Mime/Part/DataPart.php
@@ -103,6 +103,16 @@ class DataPart extends TextPart
return $headers;
}
+ public function asDebugString(): string
+ {
+ $str = parent::asDebugString();
+ if (null !== $this->filename) {
+ $str .= ' filename: '.$this->filename;
+ }
+
+ return $str;
+ }
+
private function generateContentId(): string
{
return bin2hex(random_bytes(16)).'@symfony';
diff --git a/src/Symfony/Component/Mime/Part/TextPart.php b/src/Symfony/Component/Mime/Part/TextPart.php
index 10aa94f154..77ab980219 100644
--- a/src/Symfony/Component/Mime/Part/TextPart.php
+++ b/src/Symfony/Component/Mime/Part/TextPart.php
@@ -144,6 +144,19 @@ class TextPart extends AbstractPart
return $headers;
}
+ public function asDebugString(): string
+ {
+ $str = parent::asDebugString();
+ if (null !== $this->charset) {
+ $str .= ' charset: '.$this->charset;
+ }
+ if (null !== $this->disposition) {
+ $str .= ' disposition: '.$this->disposition;
+ }
+
+ return $str;
+ }
+
private function getEncoder(): ContentEncoderInterface
{
if ('8bit' === $this->encoding) {
diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md
index eb91b1de2a..4018534374 100644
--- a/src/Symfony/Component/Yaml/CHANGELOG.md
+++ b/src/Symfony/Component/Yaml/CHANGELOG.md
@@ -6,6 +6,11 @@ CHANGELOG
* Removed support for mappings inside multi-line strings.
+4.4.0
+-----
+
+ * Added support to dump `null` as `~` by using the `Yaml::DUMP_NULL_AS_TILDE` flag.
+
4.3.0
-----
diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php
index f3f6761f81..399759ae65 100644
--- a/src/Symfony/Component/Yaml/Inline.php
+++ b/src/Symfony/Component/Yaml/Inline.php
@@ -33,6 +33,7 @@ class Inline
private static $objectSupport = false;
private static $objectForMap = false;
private static $constantSupport = false;
+ private static $nullAsTilde = false;
public static function initialize(int $flags, int $parsedLineNumber = null, string $parsedFilename = null)
{
@@ -40,6 +41,7 @@ class Inline
self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
+ self::$nullAsTilde = (bool) (Yaml::DUMP_NULL_AS_TILDE & $flags);
self::$parsedFilename = $parsedFilename;
if (null !== $parsedLineNumber) {
@@ -124,7 +126,7 @@ class Inline
throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
}
- return 'null';
+ return self::dumpNull($flags);
case $value instanceof \DateTimeInterface:
return $value->format('c');
case \is_object($value):
@@ -150,11 +152,11 @@ class Inline
throw new DumpException('Object support when dumping a YAML file has been disabled.');
}
- return 'null';
+ return self::dumpNull($flags);
case \is_array($value):
return self::dumpArray($value, $flags);
case null === $value:
- return 'null';
+ return self::dumpNull($flags);
case true === $value:
return 'true';
case false === $value:
@@ -251,6 +253,15 @@ class Inline
return sprintf('{ %s }', implode(', ', $output));
}
+ private static function dumpNull(int $flags): string
+ {
+ if (Yaml::DUMP_NULL_AS_TILDE & $flags) {
+ return '~';
+ }
+
+ return 'null';
+ }
+
/**
* Parses a YAML scalar.
*
diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php
index 6c878ff7b4..b96474f4a1 100644
--- a/src/Symfony/Component/Yaml/Tests/DumperTest.php
+++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php
@@ -504,6 +504,11 @@ YAML;
$this->expectExceptionMessage('The indentation must be greater than zero');
new Dumper(-4);
}
+
+ public function testDumpNullAsTilde()
+ {
+ $this->assertSame('{ foo: ~ }', $this->dumper->dump(['foo' => null], 0, 0, Yaml::DUMP_NULL_AS_TILDE));
+ }
}
class A
diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php
index 94a5e4ad7d..4efceb3e25 100644
--- a/src/Symfony/Component/Yaml/Yaml.php
+++ b/src/Symfony/Component/Yaml/Yaml.php
@@ -33,6 +33,7 @@ class Yaml
const PARSE_CONSTANT = 256;
const PARSE_CUSTOM_TAGS = 512;
const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
+ const DUMP_NULL_AS_TILDE = 2048;
/**
* Parses a YAML file into a PHP value.