diff --git a/README.md b/README.md index 82c0a78c..9bacfc22 100644 --- a/README.md +++ b/README.md @@ -10,4 +10,4 @@ transport. Of course, you can also implement your own transport by implementing the `Mail\Transport\TransportInterface`. - File issues at https://github.com/zendframework/zend-mail/issues -- Documentation is at https://zendframework.github.io/zend-mail/ +- Documentation is at https://docs.zendframework.com/zend-mail/ diff --git a/composer.json b/composer.json index dbfca538..7aa4ad6e 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,6 @@ "require": { "php": "^7.0 || ^5.6", "ext-iconv": "*", - "zendframework/zend-loader": "^2.5", "zendframework/zend-mime": "^2.5", "zendframework/zend-stdlib": "^2.7 || ^3.0", "zendframework/zend-validator": "^2.6" diff --git a/composer.lock b/composer.lock index c6bde4c0..41499a3e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "99fb0a39466ee5de4118b1ae973dda77", + "content-hash": "b1dc608c725b365f256e461addf28785", "packages": [ { "name": "container-interop/container-interop", @@ -86,50 +86,6 @@ ], "time": "2017-02-14T16:28:37+00:00" }, - { - "name": "zendframework/zend-loader", - "version": "2.5.1", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-loader.git", - "reference": "c5fd2f071bde071f4363def7dea8dec7393e135c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-loader/zipball/c5fd2f071bde071f4363def7dea8dec7393e135c", - "reference": "c5fd2f071bde071f4363def7dea8dec7393e135c", - "shasum": "" - }, - "require": { - "php": ">=5.3.23" - }, - "require-dev": { - "fabpot/php-cs-fixer": "1.7.*", - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5-dev", - "dev-develop": "2.6-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Loader\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "homepage": "https://github.com/zendframework/zend-loader", - "keywords": [ - "loader", - "zf2" - ], - "time": "2015-06-03T14:05:47+00:00" - }, { "name": "zendframework/zend-mime", "version": "2.6.1", diff --git a/src/Header/HeaderLoader.php b/src/Header/HeaderLoader.php index fc93f8cd..4b057484 100644 --- a/src/Header/HeaderLoader.php +++ b/src/Header/HeaderLoader.php @@ -3,43 +3,73 @@ * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository - * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com) + * @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Mail\Header; -use Zend\Loader\PluginClassLoader; - -/** - * Plugin Class Loader implementation for HTTP headers - */ -class HeaderLoader extends PluginClassLoader +class HeaderLoader { /** - * @var array Pre-aliased Header plugins + * @var array Pre-aliased Header classes */ - protected $plugins = [ - 'bcc' => 'Zend\Mail\Header\Bcc', - 'cc' => 'Zend\Mail\Header\Cc', - 'contenttype' => 'Zend\Mail\Header\ContentType', - 'content_type' => 'Zend\Mail\Header\ContentType', - 'content-type' => 'Zend\Mail\Header\ContentType', - 'contenttransferencoding' => 'Zend\Mail\Header\ContentTransferEncoding', - 'content_transfer_encoding' => 'Zend\Mail\Header\ContentTransferEncoding', - 'content-transfer-encoding' => 'Zend\Mail\Header\ContentTransferEncoding', - 'date' => 'Zend\Mail\Header\Date', - 'from' => 'Zend\Mail\Header\From', - 'message-id' => 'Zend\Mail\Header\MessageId', - 'mimeversion' => 'Zend\Mail\Header\MimeVersion', - 'mime_version' => 'Zend\Mail\Header\MimeVersion', - 'mime-version' => 'Zend\Mail\Header\MimeVersion', - 'received' => 'Zend\Mail\Header\Received', - 'replyto' => 'Zend\Mail\Header\ReplyTo', - 'reply_to' => 'Zend\Mail\Header\ReplyTo', - 'reply-to' => 'Zend\Mail\Header\ReplyTo', - 'sender' => 'Zend\Mail\Header\Sender', - 'subject' => 'Zend\Mail\Header\Subject', - 'to' => 'Zend\Mail\Header\To', + private $headerClassMap = [ + 'bcc' => Bcc::class, + 'cc' => Cc::class, + 'contenttype' => ContentType::class, + 'content_type' => ContentType::class, + 'content-type' => ContentType::class, + 'contenttransferencoding' => ContentTransferEncoding::class, + 'content_transfer_encoding' => ContentTransferEncoding::class, + 'content-transfer-encoding' => ContentTransferEncoding::class, + 'date' => Date::class, + 'from' => From::class, + 'message-id' => MessageId::class, + 'mimeversion' => MimeVersion::class, + 'mime_version' => MimeVersion::class, + 'mime-version' => MimeVersion::class, + 'received' => Received::class, + 'replyto' => ReplyTo::class, + 'reply_to' => ReplyTo::class, + 'reply-to' => ReplyTo::class, + 'sender' => Sender::class, + 'subject' => Subject::class, + 'to' => To::class, ]; + + /** + * @param string $name + * @param string|null $default + * @return string|null + */ + public function get($name, $default = null) + { + $name = $this->normalizeName($name); + return isset($this->headerClassMap[$name]) ? $this->headerClassMap[$name] : $default; + } + + /** + * @param string $name + * @return bool + */ + public function has($name) + { + return isset($this->headerClassMap[$this->normalizeName($name)]); + } + + public function add($name, $class) + { + $this->headerClassMap[$this->normalizeName($name)] = $class; + } + + public function remove($name) + { + unset($this->headerClassMap[$this->normalizeName($name)]); + } + + private function normalizeName($name) + { + return strtolower($name); + } } diff --git a/src/Headers.php b/src/Headers.php index 593d1358..1c22d183 100644 --- a/src/Headers.php +++ b/src/Headers.php @@ -13,7 +13,6 @@ use Countable; use Iterator; use Traversable; -use Zend\Loader\PluginClassLocator; /** * Basic mail headers collection functionality @@ -29,9 +28,9 @@ class Headers implements Countable, Iterator const FOLDING = "\r\n "; /** - * @var \Zend\Loader\PluginClassLoader + * @var Header\HeaderLoader */ - protected $pluginClassLoader = null; + protected $headerLoader; /** * @var array key names for $headers array @@ -117,31 +116,6 @@ public static function fromString($string, $EOL = self::EOL) return $headers; } - /** - * Set an alternate implementation for the PluginClassLoader - * - * @param PluginClassLocator $pluginClassLoader - * @return Headers - */ - public function setPluginClassLoader(PluginClassLocator $pluginClassLoader) - { - $this->pluginClassLoader = $pluginClassLoader; - return $this; - } - - /** - * Return an instance of a PluginClassLocator, lazyload and inject map if necessary - * - * @return PluginClassLocator - */ - public function getPluginClassLoader() - { - if ($this->pluginClassLoader === null) { - $this->pluginClassLoader = new Header\HeaderLoader(); - } - return $this->pluginClassLoader; - } - /** * Set the header encoding * @@ -478,7 +452,7 @@ public function forceLoading() public function loadHeader($headerLine) { list($name, ) = Header\GenericHeader::splitHeaderLine($headerLine); - $class = $this->getPluginClassLoader()->load($name) ?: Header\GenericHeader::class; + $class = $this->resolveHeaderClass($name); return $class::fromString($headerLine); } @@ -491,7 +465,7 @@ protected function lazyLoadHeader($index) $current = $this->headers[$index]; $key = $this->headersKeys[$index]; - $class = ($this->getPluginClassLoader()->load($key)) ?: 'Zend\Mail\Header\GenericHeader'; + $class = $this->resolveHeaderClass($key); $encoding = $current->getEncoding(); $headers = $class::fromString($current->toString()); @@ -523,4 +497,17 @@ protected function normalizeFieldName($fieldName) { return str_replace(['-', '_', ' ', '.'], '', strtolower($fieldName)); } + + /** + * @param string $key + * @return string + */ + private function resolveHeaderClass($key) + { + if ($this->headerLoader === null) { + $this->headerLoader = new Header\HeaderLoader(); + } + + return $this->headerLoader->get($key, Header\GenericHeader::class); + } } diff --git a/test/Header/HeaderLoaderTest.php b/test/Header/HeaderLoaderTest.php new file mode 100644 index 00000000..a0a8a832 --- /dev/null +++ b/test/Header/HeaderLoaderTest.php @@ -0,0 +1,103 @@ +headerLoader = new Header\HeaderLoader(); + } + + public function provideHeaderNames() + { + return [ + 'with existing name' => ['to', Header\To::class], + 'with non-existent name' => ['foo', null], + 'with default value' => ['foo', Header\GenericHeader::class, Header\GenericHeader::class], + ]; + } + + /** + * @param $name + * @param $expected + * @param $default + * @dataProvider provideHeaderNames + */ + public function testHeaderIsProperlyLoaded($name, $expected, $default = null) + { + $this->assertEquals($expected, $this->headerLoader->get($name, $default)); + } + + public function testHeaderExistenceIsProperlyChecked() + { + $this->assertTrue($this->headerLoader->has('to')); + $this->assertTrue($this->headerLoader->has('To')); + $this->assertTrue($this->headerLoader->has('Reply_to')); + $this->assertTrue($this->headerLoader->has('SUBJECT')); + $this->assertFalse($this->headerLoader->has('foo')); + $this->assertFalse($this->headerLoader->has('bar')); + } + + public function testHeaderCanBeAdded() + { + $this->assertFalse($this->headerLoader->has('foo')); + $this->headerLoader->add('foo', Header\GenericHeader::class); + $this->assertTrue($this->headerLoader->has('foo')); + } + + public function testHeaderCanBeRemoved() + { + $this->assertTrue($this->headerLoader->has('to')); + $this->headerLoader->remove('to'); + $this->assertFalse($this->headerLoader->has('to')); + } + + public static function expectedHeaders() + { + return [ + ['bcc', Header\Bcc::class], + ['cc', Header\Cc::class], + ['contenttype', Header\ContentType::class], + ['content_type', Header\ContentType::class], + ['content-type', Header\ContentType::class], + ['date', Header\Date::class], + ['from', Header\From::class], + ['mimeversion', Header\MimeVersion::class], + ['mime_version', Header\MimeVersion::class], + ['mime-version', Header\MimeVersion::class], + ['received', Header\Received::class], + ['replyto', Header\ReplyTo::class], + ['reply_to', Header\ReplyTo::class], + ['reply-to', Header\ReplyTo::class], + ['sender', Header\Sender::class], + ['subject', Header\Subject::class], + ['to', Header\To::class], + ]; + } + + /** + * @dataProvider expectedHeaders + * @param $name + * @param $class + */ + public function testDefaultHeadersMapResolvesProperHeader($name, $class) + { + $this->assertEquals($class, $this->headerLoader->get($name)); + } +} diff --git a/test/HeadersTest.php b/test/HeadersTest.php index 367ec6c2..c43cab4b 100644 --- a/test/HeadersTest.php +++ b/test/HeadersTest.php @@ -99,10 +99,7 @@ public function testHeadersFromStringFactoryCreatesMultipleObjects() public function testHeadersFromStringMultiHeaderWillAggregateLazyLoadedHeaders() { $headers = new Mail\Headers(); - /* @var $pcl \Zend\Loader\PluginClassLoader */ - $pcl = $headers->getPluginClassLoader(); - $pcl->registerPlugin('foo', 'Zend\Mail\Header\GenericMultiHeader'); - $headers->addHeaderLine('foo: bar1,bar2,bar3'); + $headers->addHeaderLine('foo', ['bar1@domain.com', 'bar2@domain.com', 'bar3@domain.com']); $headers->forceLoading(); $this->assertEquals(3, $headers->count()); } @@ -356,40 +353,6 @@ public function testToArrayFormatEncoded() $this->assertEquals($expected, $array); } - public static function expectedHeaders() - { - return [ - ['bcc', 'Zend\Mail\Header\Bcc'], - ['cc', 'Zend\Mail\Header\Cc'], - ['contenttype', 'Zend\Mail\Header\ContentType'], - ['content_type', 'Zend\Mail\Header\ContentType'], - ['content-type', 'Zend\Mail\Header\ContentType'], - ['date', 'Zend\Mail\Header\Date'], - ['from', 'Zend\Mail\Header\From'], - ['mimeversion', 'Zend\Mail\Header\MimeVersion'], - ['mime_version', 'Zend\Mail\Header\MimeVersion'], - ['mime-version', 'Zend\Mail\Header\MimeVersion'], - ['received', 'Zend\Mail\Header\Received'], - ['replyto', 'Zend\Mail\Header\ReplyTo'], - ['reply_to', 'Zend\Mail\Header\ReplyTo'], - ['reply-to', 'Zend\Mail\Header\ReplyTo'], - ['sender', 'Zend\Mail\Header\Sender'], - ['subject', 'Zend\Mail\Header\Subject'], - ['to', 'Zend\Mail\Header\To'], - ]; - } - - /** - * @dataProvider expectedHeaders - */ - public function testDefaultPluginLoaderIsSeededWithHeaders($plugin, $class) - { - $headers = new Mail\Headers(); - $loader = $headers->getPluginClassLoader(); - $test = $loader->load($plugin); - $this->assertEquals($class, $test); - } - public function testClone() { $headers = new Mail\Headers();