From 75ea8d0d67a213a63cf825cacfc9f913eb023c16 Mon Sep 17 00:00:00 2001 From: Giso Stallenberg Date: Thu, 22 Aug 2019 11:02:01 +0200 Subject: [PATCH] Add Address::fromString This will allow to create an Address from a string such as 'Name ' --- src/Symfony/Component/Mime/Address.php | 20 +++++ src/Symfony/Component/Mime/CHANGELOG.md | 1 + .../Component/Mime/Tests/AddressTest.php | 76 +++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/src/Symfony/Component/Mime/Address.php b/src/Symfony/Component/Mime/Address.php index ffa56352a9..d744aa1dae 100644 --- a/src/Symfony/Component/Mime/Address.php +++ b/src/Symfony/Component/Mime/Address.php @@ -23,6 +23,15 @@ use Symfony\Component\Mime\Exception\RfcComplianceException; */ final class Address { + /** + * A regex that matches a structure like 'Name '. + * It matches anything between the first < and last > as email address. + * This allows to use a single string to construct an Address, which can be convenient to use in + * config, and allows to have more readable config. + * This does not try to cover all edge cases for address. + */ + private const FROM_STRING_PATTERN = '~(?[^<]*)<(?.*)>[^>]*~'; + private static $validator; private static $encoder; @@ -100,4 +109,15 @@ final class Address return $addrs; } + + public static function fromString(string $string): self + { + if (false === strpos($string, '<')) { + return new self($string, ''); + } + if (!preg_match(self::FROM_STRING_PATTERN, $string, $matches)) { + throw new InvalidArgumentException(sprintf('Could not parse "%s" to a "%s" instance.', $string, static::class)); + } + return new self($matches['addrSpec'], trim($matches['displayName'], ' \'"')); + } } diff --git a/src/Symfony/Component/Mime/CHANGELOG.md b/src/Symfony/Component/Mime/CHANGELOG.md index 9f22a40487..6148360dd9 100644 --- a/src/Symfony/Component/Mime/CHANGELOG.md +++ b/src/Symfony/Component/Mime/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * [BC BREAK] Removed `NamedAddress` (`Address` now supports a name) * Added PHPUnit constraints * Added `AbstractPart::asDebugString()` + * Added `Address::fromString()` 4.3.3 ----- diff --git a/src/Symfony/Component/Mime/Tests/AddressTest.php b/src/Symfony/Component/Mime/Tests/AddressTest.php index 2c6245fc07..50d5780d82 100644 --- a/src/Symfony/Component/Mime/Tests/AddressTest.php +++ b/src/Symfony/Component/Mime/Tests/AddressTest.php @@ -13,6 +13,7 @@ namespace Symfony\Component\Mime\Tests; use PHPUnit\Framework\TestCase; use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\InvalidArgumentException; class AddressTest extends TestCase { @@ -77,4 +78,79 @@ class AddressTest extends TestCase { return [[''], [' '], [" \r\n "]]; } + + /** + * @dataProvider fromStringProvider + */ + public function testFromString($string, $displayName, $addrSpec) + { + $address = Address::fromString($string); + $this->assertEquals($displayName, $address->getName()); + $this->assertEquals($addrSpec, $address->getAddress()); + $fromToStringAddress = Address::fromString($address->toString()); + $this->assertEquals($displayName, $fromToStringAddress->getName()); + $this->assertEquals($addrSpec, $fromToStringAddress->getAddress()); + } + + public function testFromStringFailure() + { + $this->expectException(InvalidArgumentException::class); + Address::fromString('Jane Doe ', + '', + 'example@example.com', + ], + [ + 'Jane Doe ', + 'Jane Doe', + 'example@example.com', + ], + [ + 'Jane Doe', + 'Jane Doe', + 'example@example.com', + ], + [ + '\'Jane Doe\' ', + 'Jane Doe', + 'example@example.com', + ], + [ + '"Jane Doe" ', + 'Jane Doe', + 'example@example.com', + ], + [ + 'Jane Doe <"ex', + 'Jane Doe', + '"exle"@example.com>', + 'Jane Doe', + '"exle"@example.com', + ], + [ + 'Jane Doe > <"exle"@example.com>', + 'Jane Doe >', + '"exle"@example.com', + ], + [ + 'Jane Doe discarded', + 'Jane Doe', + 'example@example.com', + ], + ]; + } }