Merge branch '4.3' into 4.4

* 4.3:
  [Messenger] Removed named parameters and replaced with `?` placeholders for sqlsrv compatibility
  [HttpClient] use "idle" instead of "inactivity" when telling about the timeout option
  Create mailBody with only attachments part present
  [Messenger] Fix incompatibility with FrameworkBundle <4.3.1
This commit is contained in:
Fabien Potencier 2019-08-05 07:48:44 +02:00
commit 8b9de7d967
10 changed files with 53 additions and 38 deletions

View File

@ -1365,7 +1365,7 @@ class Configuration implements ConfigurationInterface
->info('A comma separated list of hosts that do not require a proxy to be reached.') ->info('A comma separated list of hosts that do not require a proxy to be reached.')
->end() ->end()
->floatNode('timeout') ->floatNode('timeout')
->info('Defaults to "default_socket_timeout" ini parameter.') ->info('The idle timeout, defaults to the "default_socket_timeout" ini parameter.')
->end() ->end()
->scalarNode('bindto') ->scalarNode('bindto')
->info('A network interface name, IP address, a host name or a UNIX socket to bind to.') ->info('A network interface name, IP address, a host name or a UNIX socket to bind to.')

View File

@ -82,7 +82,7 @@
</service> </service>
<service id="console.command.messenger_consume_messages" class="Symfony\Component\Messenger\Command\ConsumeMessagesCommand"> <service id="console.command.messenger_consume_messages" class="Symfony\Component\Messenger\Command\ConsumeMessagesCommand">
<argument type="service" id="messenger.routable_message_bus" /> <argument /> <!-- Routable message bus -->
<argument type="service" id="messenger.receiver_locator" /> <argument type="service" id="messenger.receiver_locator" />
<argument type="service" id="logger" on-invalid="null" /> <argument type="service" id="logger" on-invalid="null" />
<argument type="collection" /> <!-- Receiver names --> <argument type="collection" /> <!-- Receiver names -->

View File

@ -30,7 +30,7 @@ class ErrorChunk implements ChunkInterface
{ {
$this->offset = $offset; $this->offset = $offset;
$this->error = $error; $this->error = $error;
$this->errorMessage = null !== $error ? $error->getMessage() : 'Reading from the response stream reached the inactivity timeout.'; $this->errorMessage = null !== $error ? $error->getMessage() : 'Reading from the response stream reached the idle timeout.';
} }
/** /**

View File

@ -55,6 +55,8 @@ class ConsumeMessagesCommand extends Command
if ($routableBus instanceof ContainerInterface) { if ($routableBus instanceof ContainerInterface) {
@trigger_error(sprintf('Passing a "%s" instance as first argument to "%s()" is deprecated since Symfony 4.4, pass a "%s" instance instead.', ContainerInterface::class, __METHOD__, RoutableMessageBus::class), E_USER_DEPRECATED); @trigger_error(sprintf('Passing a "%s" instance as first argument to "%s()" is deprecated since Symfony 4.4, pass a "%s" instance instead.', ContainerInterface::class, __METHOD__, RoutableMessageBus::class), E_USER_DEPRECATED);
$routableBus = new RoutableMessageBus($routableBus); $routableBus = new RoutableMessageBus($routableBus);
} elseif (!$routableBus instanceof RoutableMessageBus) {
throw new \TypeError(sprintf('The first argument must be an instance of "%s".', RoutableMessageBus::class));
} }
if (\is_array($retryStrategyLocator)) { if (\is_array($retryStrategyLocator)) {

View File

@ -251,14 +251,19 @@ class MessengerPass implements CompilerPassInterface
$buses[$busId] = new Reference($busId); $buses[$busId] = new Reference($busId);
} }
if ($container->hasDefinition('messenger.routable_message_bus')) { if ($hasRoutableMessageBus = $container->hasDefinition('messenger.routable_message_bus')) {
$container->getDefinition('messenger.routable_message_bus') $container->getDefinition('messenger.routable_message_bus')
->replaceArgument(0, ServiceLocatorTagPass::register($container, $buses)); ->replaceArgument(0, ServiceLocatorTagPass::register($container, $buses));
} }
if ($container->hasDefinition('console.command.messenger_consume_messages')) { if ($container->hasDefinition('console.command.messenger_consume_messages')) {
$container->getDefinition('console.command.messenger_consume_messages') $consumeCommandDefinition = $container->getDefinition('console.command.messenger_consume_messages');
->replaceArgument(3, array_values($receiverNames));
if ($hasRoutableMessageBus) {
$consumeCommandDefinition->replaceArgument(0, new Reference('messenger.routable_message_bus'));
}
$consumeCommandDefinition->replaceArgument(3, array_values($receiverNames));
} }
if ($container->hasDefinition('console.command.messenger_setup_transports')) { if ($container->hasDefinition('console.command.messenger_setup_transports')) {

View File

@ -109,19 +109,19 @@ class Connection
$queryBuilder = $this->driverConnection->createQueryBuilder() $queryBuilder = $this->driverConnection->createQueryBuilder()
->insert($this->configuration['table_name']) ->insert($this->configuration['table_name'])
->values([ ->values([
'body' => ':body', 'body' => '?',
'headers' => ':headers', 'headers' => '?',
'queue_name' => ':queue_name', 'queue_name' => '?',
'created_at' => ':created_at', 'created_at' => '?',
'available_at' => ':available_at', 'available_at' => '?',
]); ]);
$this->executeQuery($queryBuilder->getSQL(), [ $this->executeQuery($queryBuilder->getSQL(), [
':body' => $body, $body,
':headers' => json_encode($headers), json_encode($headers),
':queue_name' => $this->configuration['queue_name'], $this->configuration['queue_name'],
':created_at' => self::formatDateTime($now), self::formatDateTime($now),
':available_at' => self::formatDateTime($availableAt), self::formatDateTime($availableAt),
]); ]);
return $this->driverConnection->lastInsertId(); return $this->driverConnection->lastInsertId();
@ -154,12 +154,12 @@ class Connection
$queryBuilder = $this->driverConnection->createQueryBuilder() $queryBuilder = $this->driverConnection->createQueryBuilder()
->update($this->configuration['table_name']) ->update($this->configuration['table_name'])
->set('delivered_at', ':delivered_at') ->set('delivered_at', '?')
->where('id = :id'); ->where('id = ?');
$now = new \DateTime(); $now = new \DateTime();
$this->executeQuery($queryBuilder->getSQL(), [ $this->executeQuery($queryBuilder->getSQL(), [
':id' => $doctrineEnvelope['id'], self::formatDateTime($now),
':delivered_at' => self::formatDateTime($now), $doctrineEnvelope['id'],
]); ]);
$this->driverConnection->commit(); $this->driverConnection->commit();
@ -247,10 +247,10 @@ class Connection
} }
$queryBuilder = $this->createQueryBuilder() $queryBuilder = $this->createQueryBuilder()
->where('m.id = :id'); ->where('m.id = ?');
$data = $this->executeQuery($queryBuilder->getSQL(), [ $data = $this->executeQuery($queryBuilder->getSQL(), [
'id' => $id, $id,
])->fetch(); ])->fetch();
return false === $data ? null : $this->decodeEnvelopeHeaders($data); return false === $data ? null : $this->decodeEnvelopeHeaders($data);
@ -262,13 +262,13 @@ class Connection
$redeliverLimit = (clone $now)->modify(sprintf('-%d seconds', $this->configuration['redeliver_timeout'])); $redeliverLimit = (clone $now)->modify(sprintf('-%d seconds', $this->configuration['redeliver_timeout']));
return $this->createQueryBuilder() return $this->createQueryBuilder()
->where('m.delivered_at is null OR m.delivered_at < :redeliver_limit') ->where('m.delivered_at is null OR m.delivered_at < ?')
->andWhere('m.available_at <= :now') ->andWhere('m.available_at <= ?')
->andWhere('m.queue_name = :queue_name') ->andWhere('m.queue_name = ?')
->setParameters([ ->setParameters([
':now' => self::formatDateTime($now), self::formatDateTime($redeliverLimit),
':queue_name' => $this->configuration['queue_name'], self::formatDateTime($now),
':redeliver_limit' => self::formatDateTime($redeliverLimit), $this->configuration['queue_name'],
]); ]);
} }

View File

@ -421,12 +421,12 @@ class Email extends Message
*/ */
private function generateBody(): AbstractPart private function generateBody(): AbstractPart
{ {
if (null === $this->text && null === $this->html) { [$htmlPart, $attachmentParts, $inlineParts] = $this->prepareParts();
throw new LogicException('A message must have a text and/or an HTML part.'); if (null === $this->text && null === $this->html && !$attachmentParts) {
throw new LogicException('A message must have a text or an HTML part or attachments.');
} }
$part = null === $this->text ? null : new TextPart($this->text, $this->textCharset); $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset);
[$htmlPart, $attachmentParts, $inlineParts] = $this->prepareParts();
if (null !== $htmlPart) { if (null !== $htmlPart) {
if (null !== $part) { if (null !== $part) {
$part = new AlternativePart($part, $htmlPart); $part = new AlternativePart($part, $htmlPart);
@ -440,7 +440,11 @@ class Email extends Message
} }
if ($attachmentParts) { if ($attachmentParts) {
$part = new MixedPart($part, ...$attachmentParts); if ($part) {
$part = new MixedPart($part, ...$attachmentParts);
} else {
$part = new MixedPart(...$attachmentParts);
}
} }
return $part; return $part;

View File

@ -284,6 +284,10 @@ class EmailTest extends TestCase
$e->html('html content'); $e->html('html content');
$this->assertEquals(new MixedPart($html, $att), $e->getBody()); $this->assertEquals(new MixedPart($html, $att), $e->getBody());
$e = new Email();
$e->attach($file);
$this->assertEquals(new MixedPart($att), $e->getBody());
$e = new Email(); $e = new Email();
$e->html('html content'); $e->html('html content');
$e->text('text content'); $e->text('text content');

View File

@ -27,7 +27,7 @@ use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
interface ChunkInterface interface ChunkInterface
{ {
/** /**
* Tells when the inactivity timeout has been reached. * Tells when the idle timeout has been reached.
* *
* @throws TransportExceptionInterface on a network error * @throws TransportExceptionInterface on a network error
*/ */
@ -36,21 +36,21 @@ interface ChunkInterface
/** /**
* Tells when headers just arrived. * Tells when headers just arrived.
* *
* @throws TransportExceptionInterface on a network error or when the inactivity timeout is reached * @throws TransportExceptionInterface on a network error or when the idle timeout is reached
*/ */
public function isFirst(): bool; public function isFirst(): bool;
/** /**
* Tells when the body just completed. * Tells when the body just completed.
* *
* @throws TransportExceptionInterface on a network error or when the inactivity timeout is reached * @throws TransportExceptionInterface on a network error or when the idle timeout is reached
*/ */
public function isLast(): bool; public function isLast(): bool;
/** /**
* Returns the content of the response chunk. * Returns the content of the response chunk.
* *
* @throws TransportExceptionInterface on a network error or when the inactivity timeout is reached * @throws TransportExceptionInterface on a network error or when the idle timeout is reached
*/ */
public function getContent(): string; public function getContent(): string;

View File

@ -52,7 +52,7 @@ interface HttpClientInterface
'resolve' => [], // string[] - a map of host to IP address that SHOULD replace DNS resolution 'resolve' => [], // string[] - a map of host to IP address that SHOULD replace DNS resolution
'proxy' => null, // string - by default, the proxy-related env vars handled by curl SHOULD be honored 'proxy' => null, // string - by default, the proxy-related env vars handled by curl SHOULD be honored
'no_proxy' => null, // string - a comma separated list of hosts that do not require a proxy to be reached 'no_proxy' => null, // string - a comma separated list of hosts that do not require a proxy to be reached
'timeout' => null, // float - the inactivity timeout - defaults to ini_get('default_socket_timeout') 'timeout' => null, // float - the idle timeout - defaults to ini_get('default_socket_timeout')
'bindto' => '0', // string - the interface or the local socket to bind to 'bindto' => '0', // string - the interface or the local socket to bind to
'verify_peer' => true, // see https://php.net/context.ssl for the following options 'verify_peer' => true, // see https://php.net/context.ssl for the following options
'verify_host' => true, 'verify_host' => true,
@ -85,7 +85,7 @@ interface HttpClientInterface
* Yields responses chunk by chunk as they complete. * Yields responses chunk by chunk as they complete.
* *
* @param ResponseInterface|ResponseInterface[]|iterable $responses One or more responses created by the current HTTP client * @param ResponseInterface|ResponseInterface[]|iterable $responses One or more responses created by the current HTTP client
* @param float|null $timeout The inactivity timeout before exiting the iterator * @param float|null $timeout The idle timeout before yielding timeout chunks
*/ */
public function stream($responses, float $timeout = null): ResponseStreamInterface; public function stream($responses, float $timeout = null): ResponseStreamInterface;
} }