From 7e916534c81083736b2983f428af4daf93831585 Mon Sep 17 00:00:00 2001 From: Moritz Friedrich Date: Wed, 13 Jul 2022 15:58:20 +0200 Subject: [PATCH] Ensured special headers are only added once --- src/Messages/HeaderTrait.php | 44 ++++--- .../Messages/MailgunTemplatedMessageTest.php | 117 ++++++++++++++++++ 2 files changed, 144 insertions(+), 17 deletions(-) diff --git a/src/Messages/HeaderTrait.php b/src/Messages/HeaderTrait.php index 70cce99..79ba611 100644 --- a/src/Messages/HeaderTrait.php +++ b/src/Messages/HeaderTrait.php @@ -67,7 +67,7 @@ public function setReplyTo(string|array $replyTo): void $target = $this->resolveTarget($replyTo); if ($target) { - $this->addHeader('reply-to', $target); + $this->addHeader('reply-to', $target, true); } } @@ -81,24 +81,29 @@ public function setReturnPath(string|array $returnPath): void $target = $this->resolveTarget($returnPath); if ($target) { - $this->addHeader('return-path', $target); + $this->addHeader('return-path', $target, true); } } /** * Adds a header to the message. * - * @param string $name Name of the header. - * @param string|string[] $value Value of the header, or multiple values as - * an array. + * @param string $name Name of the header. + * @param string|string[] $value Value of the header, or multiple values + * as an array. + * @param bool $replace Whether any existing header value should + * be replaced with the new value. * * @psalm-suppress MixedPropertyTypeCoercion */ - public function addHeader(string $name, string|array $value): void - { + public function addHeader( + string $name, + string|array $value, + bool $replace = false + ): void { $name = $this->normalizeHeaderName($name); - if ( ! $this->hasHeader($name)) { + if ($replace || ! $this->hasHeader($name)) { $this->headers[$name] = []; } @@ -148,16 +153,21 @@ public function hasReturnPath(): bool /** * Sets a single header. * - * @param string $name Name of the header. - * @param string|string[] $value Value of the header, or multiple values as - * an array. + * @param string $name Name of the header. + * @param string|string[] $value Value of the header, or multiple values + * as an array. + * @param bool $replace Whether any existing header value should + * be replaced with the new value. * * @return T Instance for chaining. * @see self::addHeader() */ - public function header(string $name, string|array $value): static - { - $this->addHeader($name, $value); + public function header( + string $name, + string|array $value, + bool $replace = false + ): static { + $this->addHeader($name, $value, $replace); return $this; } @@ -198,11 +208,11 @@ public function removeHeader(string $name): void * @param string|array $replyTo Reply to address. * * @return T Instance for chaining. - * @see self::replyTo() + * @see self::setReplyTo() */ public function replyTo(string|array $replyTo): static { - $this->replyTo($replyTo); + $this->setReplyTo($replyTo); return $this; } @@ -213,7 +223,7 @@ public function replyTo(string|array $replyTo): static * @param string|array $returnPath Reply to address. * * @return T Instance for chaining. - * @see self::returnPath() + * @see self::setReturnPath() */ public function returnPath(string|array $returnPath): static { diff --git a/tests/Unit/Messages/MailgunTemplatedMessageTest.php b/tests/Unit/Messages/MailgunTemplatedMessageTest.php index a8e3ae9..f2a2a48 100644 --- a/tests/Unit/Messages/MailgunTemplatedMessageTest.php +++ b/tests/Unit/Messages/MailgunTemplatedMessageTest.php @@ -27,6 +27,26 @@ class MailgunTemplatedMessageTest extends TestCase { + /** + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::getHeaders + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::header + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::addHeader + */ + public function testAppendsHeaders(): void + { + $message = new MailgunTemplatedMessage('foo'); + + self::assertEmpty($message->getHeaders()); + $message->header('foo', 'bar'); + self::assertEquals(['bar'], $message->getHeaders()['foo']); + $message->addHeader('foo', 'baz'); + self::assertEquals(['bar', 'baz'], $message->getHeaders()['foo']); + $message->addHeader('foo', 'quz', true); + self::assertEquals(['quz'], $message->getHeaders()['foo']); + } + /** * @throws ExpectationFailedException * @throws InvalidArgumentException @@ -526,6 +546,103 @@ public function testRecipientSetting(): void self::assertSame('bar', $message->getRecipient()); } + /** + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * @throws JsonException + * @throws \PHPUnit\Framework\Exception + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::hasHeader + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::toArray + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::addHeader + */ + public function testRemovesPrefixFromHeaders(): void + { + $message = new MailgunTemplatedMessage('foo'); + $message->addHeader('h:foo', 'bar'); + self::assertTrue($message->hasHeader('foo')); + self::assertArrayHasKey('h:foo', $message->toArray()); + } + + /** + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * @throws JsonException + * @throws \PHPUnit\Framework\Exception + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::hasOption + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::toArray + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::addOption + */ + public function testRemovesPrefixFromOptions(): void + { + $message = new MailgunTemplatedMessage('foo'); + $message->addOption('o:foo', 'bar'); + self::assertTrue($message->hasOption('foo')); + self::assertFalse($message->hasOption('o:foo')); + self::assertArrayHasKey('o:foo', $message->toArray()); + } + + /** + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * @throws JsonException + * @throws \PHPUnit\Framework\Exception + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::hasParam + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::toArray + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::addParam + */ + public function testRemovesPrefixFromParams(): void + { + $message = new MailgunTemplatedMessage('foo'); + $message->addParam('v:foo', 'bar'); + self::assertTrue($message->hasParam('foo')); + self::assertFalse($message->hasParam('v:foo')); + self::assertArrayHasKey('v:foo', $message->toArray()); + } + + /** + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::replyTo + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::setReplyTo + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::hasReplyTo + */ + public function testReplyToSetting(): void + { + $message = new MailgunTemplatedMessage('foo'); + + self::assertFalse($message->hasReplyTo()); + self::assertFalse($message->hasHeader('return-path')); + self::assertNull($message->getHeaders()['return-path'] ?? null); + $message->setReplyTo('foo'); + self::assertEquals(['foo'], $message->getHeaders()['reply-to']); + self::assertTrue($message->hasReplyTo()); + $message->replyTo('bar'); + self::assertEquals(['bar'], $message->getHeaders()['reply-to']); + self::assertTrue($message->hasReplyTo()); + } + + /** + * @throws ExpectationFailedException + * @throws InvalidArgumentException + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::returnPath + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::setReturnPath + * @covers \Matchory\MailgunTemplatedMessages\Messages\MailgunTemplatedMessage::hasReturnPath + */ + public function testReturnPathSetting(): void + { + $message = new MailgunTemplatedMessage('foo'); + + self::assertFalse($message->hasReturnPath()); + self::assertFalse($message->hasHeader('return-path')); + self::assertNull($message->getHeaders()['return-path'] ?? null); + $message->setReturnPath('foo'); + self::assertEquals(['foo'], $message->getHeaders()['return-path']); + self::assertTrue($message->hasReturnPath()); + $message->returnPath('bar'); + self::assertEquals(['bar'], $message->getHeaders()['return-path']); + self::assertTrue($message->hasReturnPath()); + } + /** * @throws ExpectationFailedException * @throws InvalidArgumentException