Merge branch '4.4'
* 4.4: [PhpUnitBridge] fix internal annotation [Mime] added AbstractPart::asDebugString() [Mailer] added a name to the transport [Mailer] added missing entry in the CHANGELOG [FrameworkBundle] add config translator cache_dir [Yaml] Add flag to dump NULL as ~
This commit is contained in:
commit
d336b115a1
@ -17,7 +17,7 @@ use PHPUnit\Framework\Constraint\StringContains;
|
|||||||
use PHPUnit\Framework\Constraint\TraversableContains;
|
use PHPUnit\Framework\Constraint\TraversableContains;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* This trait is @internal
|
||||||
*/
|
*/
|
||||||
trait PolyfillAssertTrait
|
trait PolyfillAssertTrait
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ use PHPUnit\Framework\MockObject\MockObject;
|
|||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* This trait is @internal
|
||||||
*/
|
*/
|
||||||
trait PolyfillTestCaseTrait
|
trait PolyfillTestCaseTrait
|
||||||
{
|
{
|
||||||
|
@ -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);
|
$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);
|
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'
|
file_put_contents('phpunit', <<<'EOPHP'
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
@ -652,6 +652,7 @@ class Configuration implements ConfigurationInterface
|
|||||||
->end()
|
->end()
|
||||||
->booleanNode('logging')->defaultValue(false)->end()
|
->booleanNode('logging')->defaultValue(false)->end()
|
||||||
->scalarNode('formatter')->defaultValue('translator.formatter.default')->end()
|
->scalarNode('formatter')->defaultValue('translator.formatter.default')->end()
|
||||||
|
->scalarNode('cache_dir')->defaultValue('%kernel.cache_dir%/translations')->end()
|
||||||
->scalarNode('default_path')
|
->scalarNode('default_path')
|
||||||
->info('The default path used to load translations')
|
->info('The default path used to load translations')
|
||||||
->defaultValue('%kernel.project_dir%/translations')
|
->defaultValue('%kernel.project_dir%/translations')
|
||||||
|
@ -992,6 +992,10 @@ class FrameworkExtension extends Extension
|
|||||||
$translator = $container->findDefinition('translator.default');
|
$translator = $container->findDefinition('translator.default');
|
||||||
$translator->addMethodCall('setFallbackLocales', [$config['fallbacks'] ?: [$defaultLocale]]);
|
$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.logging', $config['logging']);
|
||||||
$container->setParameter('translator.default_path', $config['default_path']);
|
$container->setParameter('translator.default_path', $config['default_path']);
|
||||||
|
|
||||||
|
@ -173,6 +173,7 @@
|
|||||||
<xsd:attribute name="fallback" type="xsd:string" />
|
<xsd:attribute name="fallback" type="xsd:string" />
|
||||||
<xsd:attribute name="logging" type="xsd:boolean" />
|
<xsd:attribute name="logging" type="xsd:boolean" />
|
||||||
<xsd:attribute name="formatter" type="xsd:string" />
|
<xsd:attribute name="formatter" type="xsd:string" />
|
||||||
|
<xsd:attribute name="cache-dir" type="xsd:string" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="validation">
|
<xsd:complexType name="validation">
|
||||||
|
@ -225,6 +225,7 @@ class ConfigurationTest extends TestCase
|
|||||||
'translator' => [
|
'translator' => [
|
||||||
'enabled' => !class_exists(FullStack::class),
|
'enabled' => !class_exists(FullStack::class),
|
||||||
'fallbacks' => [],
|
'fallbacks' => [],
|
||||||
|
'cache_dir' => '%kernel.cache_dir%/translations',
|
||||||
'logging' => false,
|
'logging' => false,
|
||||||
'formatter' => 'translator.formatter.default',
|
'formatter' => 'translator.formatter.default',
|
||||||
'paths' => [],
|
'paths' => [],
|
||||||
|
@ -46,6 +46,7 @@ $container->loadFromExtension('framework', [
|
|||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
'fallback' => 'fr',
|
'fallback' => 'fr',
|
||||||
'paths' => ['%kernel.project_dir%/Fixtures/translations'],
|
'paths' => ['%kernel.project_dir%/Fixtures/translations'],
|
||||||
|
'cache_dir' => '%kernel.cache_dir%/translations',
|
||||||
],
|
],
|
||||||
'validation' => [
|
'validation' => [
|
||||||
'enabled' => true,
|
'enabled' => true,
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$container->loadFromExtension('framework', [
|
||||||
|
'translator' => [
|
||||||
|
'cache_dir' => null,
|
||||||
|
],
|
||||||
|
]);
|
@ -26,7 +26,7 @@
|
|||||||
</framework:format>
|
</framework:format>
|
||||||
</framework:request>
|
</framework:request>
|
||||||
<framework:assets version="v1" />
|
<framework:assets version="v1" />
|
||||||
<framework:translator enabled="true" fallback="fr" logging="true">
|
<framework:translator enabled="true" fallback="fr" logging="true" cache-dir="%kernel.cache_dir%/translations">
|
||||||
<framework:path>%kernel.project_dir%/Fixtures/translations</framework:path>
|
<framework:path>%kernel.project_dir%/Fixtures/translations</framework:path>
|
||||||
</framework:translator>
|
</framework:translator>
|
||||||
<framework:validation enabled="true" />
|
<framework:validation enabled="true" />
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" ?>
|
||||||
|
|
||||||
|
<container xmlns="http://symfony.com/schema/dic/services"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||||
|
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||||
|
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||||
|
|
||||||
|
<framework:config secret="s3cr3t">
|
||||||
|
<framework:translator enabled="true" fallback="fr" logging="true" cache-dir="null" />
|
||||||
|
</framework:config>
|
||||||
|
</container>
|
@ -36,6 +36,7 @@ framework:
|
|||||||
enabled: true
|
enabled: true
|
||||||
fallback: fr
|
fallback: fr
|
||||||
default_path: '%kernel.project_dir%/translations'
|
default_path: '%kernel.project_dir%/translations'
|
||||||
|
cache_dir: '%kernel.cache_dir%/translations'
|
||||||
paths: ['%kernel.project_dir%/Fixtures/translations']
|
paths: ['%kernel.project_dir%/Fixtures/translations']
|
||||||
validation:
|
validation:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
framework:
|
||||||
|
translator:
|
||||||
|
cache_dir: ~
|
@ -54,6 +54,7 @@ use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
|
|||||||
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
|
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
|
||||||
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
|
use Symfony\Component\Validator\Mapping\Loader\PropertyInfoLoader;
|
||||||
use Symfony\Component\Workflow;
|
use Symfony\Component\Workflow;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
abstract class FrameworkExtensionTest extends TestCase
|
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');
|
$this->assertEquals('translator.default', (string) $container->getAlias('translator'), '->registerTranslatorConfiguration() redefines translator service from identity to real translator');
|
||||||
$options = $container->getDefinition('translator.default')->getArgument(4);
|
$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']);
|
$files = array_map('realpath', $options['resource_files']['en']);
|
||||||
$ref = new \ReflectionClass('Symfony\Component\Validator\Validation');
|
$ref = new \ReflectionClass('Symfony\Component\Validator\Validation');
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
@ -739,6 +743,13 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||||||
$this->assertEquals(['en', 'fr'], $calls[1][1][0]);
|
$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()
|
public function testValidation()
|
||||||
{
|
{
|
||||||
$container = $this->createContainerFromFile('full');
|
$container = $this->createContainerFromFile('full');
|
||||||
|
@ -42,6 +42,11 @@ class MailerTest extends AbstractWebTestCase
|
|||||||
$this->onDoSend = $onDoSend;
|
$this->onDoSend = $onDoSend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return 'dummy://local';
|
||||||
|
}
|
||||||
|
|
||||||
protected function doSend(SentMessage $message): void
|
protected function doSend(SentMessage $message): void
|
||||||
{
|
{
|
||||||
$onDoSend = $this->onDoSend;
|
$onDoSend = $this->onDoSend;
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
"symfony/dom-crawler": "<4.4",
|
"symfony/dom-crawler": "<4.4",
|
||||||
"symfony/form": "<4.4",
|
"symfony/form": "<4.4",
|
||||||
"symfony/lock": "<4.4",
|
"symfony/lock": "<4.4",
|
||||||
|
"symfony/mailer": "<4.4",
|
||||||
"symfony/messenger": "<4.4",
|
"symfony/messenger": "<4.4",
|
||||||
"symfony/property-info": "<4.4",
|
"symfony/property-info": "<4.4",
|
||||||
"symfony/serializer": "<4.4",
|
"symfony/serializer": "<4.4",
|
||||||
|
@ -43,6 +43,11 @@ class SesApiTransport extends AbstractApiTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
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
|
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||||
{
|
{
|
||||||
$date = gmdate('D, d M Y H:i:s e');
|
$date = gmdate('D, d M Y H:i:s e');
|
||||||
|
@ -42,6 +42,11 @@ class SesHttpTransport extends AbstractHttpTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
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
|
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||||
{
|
{
|
||||||
$date = gmdate('D, d M Y H:i:s e');
|
$date = gmdate('D, d M Y H:i:s e');
|
||||||
|
@ -36,6 +36,11 @@ class MandrillApiTransport extends AbstractApiTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
parent::__construct($client, $dispatcher, $logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return sprintf('api://mandrill');
|
||||||
|
}
|
||||||
|
|
||||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||||
{
|
{
|
||||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||||
|
@ -34,6 +34,11 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
parent::__construct($client, $dispatcher, $logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return sprintf('http://mandrill');
|
||||||
|
}
|
||||||
|
|
||||||
protected function doSendHttp(SentMessage $message): ResponseInterface
|
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||||
{
|
{
|
||||||
$envelope = $message->getEnvelope();
|
$envelope = $message->getEnvelope();
|
||||||
|
@ -41,6 +41,11 @@ class MailgunApiTransport extends AbstractApiTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
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
|
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||||
{
|
{
|
||||||
$body = new FormDataPart($this->getPayload($email, $envelope));
|
$body = new FormDataPart($this->getPayload($email, $envelope));
|
||||||
|
@ -40,6 +40,11 @@ class MailgunHttpTransport extends AbstractHttpTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
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
|
protected function doSendHttp(SentMessage $message): ResponseInterface
|
||||||
{
|
{
|
||||||
$body = new FormDataPart([
|
$body = new FormDataPart([
|
||||||
|
@ -36,6 +36,11 @@ class PostmarkApiTransport extends AbstractApiTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
parent::__construct($client, $dispatcher, $logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return sprintf('api://postmark');
|
||||||
|
}
|
||||||
|
|
||||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||||
{
|
{
|
||||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||||
|
@ -37,6 +37,11 @@ class SendgridApiTransport extends AbstractApiTransport
|
|||||||
parent::__construct($client, $dispatcher, $logger);
|
parent::__construct($client, $dispatcher, $logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return sprintf('api://sendgrid');
|
||||||
|
}
|
||||||
|
|
||||||
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
protected function doSendApi(Email $email, SmtpEnvelope $envelope): ResponseInterface
|
||||||
{
|
{
|
||||||
$response = $this->client->request('POST', self::ENDPOINT, [
|
$response = $this->client->request('POST', self::ENDPOINT, [
|
||||||
|
@ -4,12 +4,14 @@ CHANGELOG
|
|||||||
4.4.0
|
4.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* [BC BREAK] `TransportInterface` has a new `getName()` method
|
||||||
* [BC BREAK] Classes `AbstractApiTransport` and `AbstractHttpTransport` moved under `Transport` sub-namespace.
|
* [BC BREAK] Classes `AbstractApiTransport` and `AbstractHttpTransport` moved under `Transport` sub-namespace.
|
||||||
* [BC BREAK] Transports depend on `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`
|
* [BC BREAK] Transports depend on `Symfony\Contracts\EventDispatcher\EventDispatcherInterface`
|
||||||
instead of `Symfony\Component\EventDispatcher\EventDispatcherInterface`.
|
instead of `Symfony\Component\EventDispatcher\EventDispatcherInterface`.
|
||||||
* Added possibility to register custom transport for dsn by implementing
|
* Added possibility to register custom transport for dsn by implementing
|
||||||
`Symfony\Component\Mailer\Transport\TransportFactoryInterface` and tagging with `mailer.transport_factory` tag in DI.
|
`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 `Symfony\Component\Mailer\Test\TransportFactoryTestCase` to ease testing custom transport factories.
|
||||||
|
* Added `SentMessage::getDebug()` and `TransportExceptionInterface::getDebug` to help debugging
|
||||||
|
|
||||||
4.3.0
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
@ -69,6 +69,9 @@ abstract class TransportFactoryTestCase extends TestCase
|
|||||||
$factory = $this->getFactory();
|
$factory = $this->getFactory();
|
||||||
|
|
||||||
$this->assertEquals($transport, $factory->create($dsn));
|
$this->assertEquals($transport, $factory->create($dsn));
|
||||||
|
if ('smtp' !== $dsn->getScheme()) {
|
||||||
|
$this->assertStringMatchesFormat($dsn->getScheme().'://%S'.$dsn->getHost().'%S', $transport->getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +29,16 @@ class FailoverTransportTest extends TestCase
|
|||||||
new FailoverTransport([]);
|
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()
|
public function testSendFirstWork()
|
||||||
{
|
{
|
||||||
$t1 = $this->createMock(TransportInterface::class);
|
$t1 = $this->createMock(TransportInterface::class);
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
|
}
|
@ -28,6 +28,16 @@ class RoundRobinTransportTest extends TestCase
|
|||||||
new RoundRobinTransport([]);
|
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()
|
public function testSendAlternate()
|
||||||
{
|
{
|
||||||
$t1 = $this->createMock(TransportInterface::class);
|
$t1 = $this->createMock(TransportInterface::class);
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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());
|
||||||
|
}
|
||||||
|
}
|
@ -68,6 +68,11 @@ class DummyTransport implements Transport\TransportInterface
|
|||||||
{
|
{
|
||||||
throw new \BadMethodCallException('This method newer should be called.');
|
throw new \BadMethodCallException('This method newer should be called.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return sprintf('dummy://local');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyTransportFactory implements Transport\TransportFactoryInterface
|
class DummyTransportFactory implements Transport\TransportFactoryInterface
|
||||||
|
@ -39,6 +39,8 @@ abstract class AbstractTransport implements TransportInterface
|
|||||||
$this->logger = $logger ?: new NullLogger();
|
$this->logger = $logger ?: new NullLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract public function getName(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the maximum number of messages to send per second (0 to disable).
|
* Sets the maximum number of messages to send per second (0 to disable).
|
||||||
*/
|
*/
|
||||||
|
@ -28,4 +28,9 @@ class FailoverTransport extends RoundRobinTransport
|
|||||||
|
|
||||||
return $this->currentTransport;
|
return $this->currentTransport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getNameSymbol(): string
|
||||||
|
{
|
||||||
|
return '||';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,9 @@ final class NullTransport extends AbstractTransport
|
|||||||
protected function doSend(SentMessage $message): void
|
protected function doSend(SentMessage $message): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return 'smtp://null';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,13 @@ class RoundRobinTransport implements TransportInterface
|
|||||||
throw new TransportException('All transports failed.');
|
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.
|
* Rotates the transport list around and returns the first instance.
|
||||||
*/
|
*/
|
||||||
@ -90,6 +97,11 @@ class RoundRobinTransport implements TransportInterface
|
|||||||
return $this->deadTransports->contains($transport);
|
return $this->deadTransports->contains($transport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getNameSymbol(): string
|
||||||
|
{
|
||||||
|
return '&&';
|
||||||
|
}
|
||||||
|
|
||||||
private function moveCursor(int $cursor): int
|
private function moveCursor(int $cursor): int
|
||||||
{
|
{
|
||||||
return ++$cursor >= \count($this->transports) ? 0 : $cursor;
|
return ++$cursor >= \count($this->transports) ? 0 : $cursor;
|
||||||
|
@ -73,6 +73,11 @@ class SendmailTransport extends AbstractTransport
|
|||||||
return parent::send($message, $envelope);
|
return parent::send($message, $envelope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return $this->transport->getName();
|
||||||
|
}
|
||||||
|
|
||||||
protected function doSend(SentMessage $message): void
|
protected function doSend(SentMessage $message): void
|
||||||
{
|
{
|
||||||
$this->getLogger()->debug(sprintf('Email transport "%s" starting', __CLASS__));
|
$this->getLogger()->debug(sprintf('Email transport "%s" starting', __CLASS__));
|
||||||
|
@ -126,6 +126,15 @@ class SmtpTransport extends AbstractTransport
|
|||||||
return $message;
|
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.
|
* Runs a command against the stream, expecting the given response codes.
|
||||||
*
|
*
|
||||||
|
@ -30,4 +30,6 @@ interface TransportInterface
|
|||||||
* @throws TransportExceptionInterface
|
* @throws TransportExceptionInterface
|
||||||
*/
|
*/
|
||||||
public function send(RawMessage $message, SmtpEnvelope $envelope = null): ?SentMessage;
|
public function send(RawMessage $message, SmtpEnvelope $envelope = null): ?SentMessage;
|
||||||
|
|
||||||
|
public function getName(): string;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
4.4.0
|
||||||
|
-----
|
||||||
|
|
||||||
|
* Added `AbstractPart::asDebugString()`
|
||||||
|
|
||||||
4.3.3
|
4.3.3
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -74,6 +74,20 @@ abstract class AbstractMultipartPart extends AbstractPart
|
|||||||
yield '--'.$this->getBoundary()."--\r\n";
|
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
|
private function getBoundary(): string
|
||||||
{
|
{
|
||||||
if (null === $this->boundary) {
|
if (null === $this->boundary) {
|
||||||
|
@ -50,6 +50,11 @@ abstract class AbstractPart
|
|||||||
yield from $this->bodyToIterable();
|
yield from $this->bodyToIterable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function asDebugString(): string
|
||||||
|
{
|
||||||
|
return $this->getMediaType().'/'.$this->getMediaSubtype();
|
||||||
|
}
|
||||||
|
|
||||||
abstract public function bodyToString(): string;
|
abstract public function bodyToString(): string;
|
||||||
|
|
||||||
abstract public function bodyToIterable(): iterable;
|
abstract public function bodyToIterable(): iterable;
|
||||||
|
@ -103,6 +103,16 @@ class DataPart extends TextPart
|
|||||||
return $headers;
|
return $headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function asDebugString(): string
|
||||||
|
{
|
||||||
|
$str = parent::asDebugString();
|
||||||
|
if (null !== $this->filename) {
|
||||||
|
$str .= ' filename: '.$this->filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
private function generateContentId(): string
|
private function generateContentId(): string
|
||||||
{
|
{
|
||||||
return bin2hex(random_bytes(16)).'@symfony';
|
return bin2hex(random_bytes(16)).'@symfony';
|
||||||
|
@ -144,6 +144,19 @@ class TextPart extends AbstractPart
|
|||||||
return $headers;
|
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
|
private function getEncoder(): ContentEncoderInterface
|
||||||
{
|
{
|
||||||
if ('8bit' === $this->encoding) {
|
if ('8bit' === $this->encoding) {
|
||||||
|
@ -6,6 +6,11 @@ CHANGELOG
|
|||||||
|
|
||||||
* Removed support for mappings inside multi-line strings.
|
* 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
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ class Inline
|
|||||||
private static $objectSupport = false;
|
private static $objectSupport = false;
|
||||||
private static $objectForMap = false;
|
private static $objectForMap = false;
|
||||||
private static $constantSupport = false;
|
private static $constantSupport = false;
|
||||||
|
private static $nullAsTilde = false;
|
||||||
|
|
||||||
public static function initialize(int $flags, int $parsedLineNumber = null, string $parsedFilename = null)
|
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::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags);
|
||||||
self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
|
self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags);
|
||||||
self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
|
self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags);
|
||||||
|
self::$nullAsTilde = (bool) (Yaml::DUMP_NULL_AS_TILDE & $flags);
|
||||||
self::$parsedFilename = $parsedFilename;
|
self::$parsedFilename = $parsedFilename;
|
||||||
|
|
||||||
if (null !== $parsedLineNumber) {
|
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)));
|
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:
|
case $value instanceof \DateTimeInterface:
|
||||||
return $value->format('c');
|
return $value->format('c');
|
||||||
case \is_object($value):
|
case \is_object($value):
|
||||||
@ -150,11 +152,11 @@ class Inline
|
|||||||
throw new DumpException('Object support when dumping a YAML file has been disabled.');
|
throw new DumpException('Object support when dumping a YAML file has been disabled.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'null';
|
return self::dumpNull($flags);
|
||||||
case \is_array($value):
|
case \is_array($value):
|
||||||
return self::dumpArray($value, $flags);
|
return self::dumpArray($value, $flags);
|
||||||
case null === $value:
|
case null === $value:
|
||||||
return 'null';
|
return self::dumpNull($flags);
|
||||||
case true === $value:
|
case true === $value:
|
||||||
return 'true';
|
return 'true';
|
||||||
case false === $value:
|
case false === $value:
|
||||||
@ -251,6 +253,15 @@ class Inline
|
|||||||
return sprintf('{ %s }', implode(', ', $output));
|
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.
|
* Parses a YAML scalar.
|
||||||
*
|
*
|
||||||
|
@ -504,6 +504,11 @@ YAML;
|
|||||||
$this->expectExceptionMessage('The indentation must be greater than zero');
|
$this->expectExceptionMessage('The indentation must be greater than zero');
|
||||||
new Dumper(-4);
|
new Dumper(-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDumpNullAsTilde()
|
||||||
|
{
|
||||||
|
$this->assertSame('{ foo: ~ }', $this->dumper->dump(['foo' => null], 0, 0, Yaml::DUMP_NULL_AS_TILDE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class A
|
class A
|
||||||
|
@ -33,6 +33,7 @@ class Yaml
|
|||||||
const PARSE_CONSTANT = 256;
|
const PARSE_CONSTANT = 256;
|
||||||
const PARSE_CUSTOM_TAGS = 512;
|
const PARSE_CUSTOM_TAGS = 512;
|
||||||
const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
|
const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
|
||||||
|
const DUMP_NULL_AS_TILDE = 2048;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a YAML file into a PHP value.
|
* Parses a YAML file into a PHP value.
|
||||||
|
Reference in New Issue
Block a user