diff --git a/composer.json b/composer.json index b119f099..4f86b78d 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,6 @@ "require": { "php": "^5.6 || ^7.0", "ext-iconv": "*", - "laminas/laminas-loader": "^2.5", "laminas/laminas-mime": "^2.5", "laminas/laminas-stdlib": "^2.7 || ^3.0", "laminas/laminas-validator": "^2.10.2", diff --git a/src/Header/HeaderLoader.php b/src/Header/HeaderLoader.php index 026c5c15..d9996a31 100644 --- a/src/Header/HeaderLoader.php +++ b/src/Header/HeaderLoader.php @@ -8,12 +8,10 @@ namespace Laminas\Mail\Header; -use Laminas\Loader\PluginClassLoader; - /** * Plugin Class Loader implementation for HTTP headers */ -class HeaderLoader extends PluginClassLoader +class HeaderLoader { /** * @var array Pre-aliased Header plugins @@ -46,4 +44,39 @@ class HeaderLoader extends PluginClassLoader '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 fb57d201..e561ec85 100644 --- a/src/Headers.php +++ b/src/Headers.php @@ -11,7 +11,6 @@ use ArrayIterator; use Countable; use Iterator; -use Laminas\Loader\PluginClassLocator; use Laminas\Mail\Header\GenericHeader; use Laminas\Mail\Header\HeaderInterface; use Traversable; @@ -30,9 +29,9 @@ class Headers implements Countable, Iterator const FOLDING = "\r\n "; /** - * @var \Laminas\Loader\PluginClassLoader + * @var Header\HeaderLoader */ - protected $pluginClassLoader = null; + protected $headerLoader = null; /** * @var array key names for $headers array @@ -118,31 +117,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 * @@ -481,7 +455,7 @@ public function loadHeader($headerLine) list($name, ) = Header\GenericHeader::splitHeaderLine($headerLine); /** @var HeaderInterface $class */ - $class = $this->getPluginClassLoader()->load($name) ?: Header\GenericHeader::class; + $class = $this->resolveHeaderClass($name); return $class::fromString($headerLine); } @@ -496,7 +470,7 @@ protected function lazyLoadHeader($index) $key = $this->headersKeys[$index]; /** @var GenericHeader $class */ - $class = ($this->getPluginClassLoader()->load($key)) ?: Header\GenericHeader::class; + $class = $this->resolveHeaderClass($key); $encoding = $current->getEncoding(); $headers = $class::fromString($current->toString()); @@ -528,4 +502,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..dd553e1c --- /dev/null +++ b/test/Header/HeaderLoaderTest.php @@ -0,0 +1,102 @@ +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)); + } +} \ No newline at end of file diff --git a/test/HeadersTest.php b/test/HeadersTest.php index c747feb9..2b483e23 100644 --- a/test/HeadersTest.php +++ b/test/HeadersTest.php @@ -117,10 +117,7 @@ public function testPluginClassLoaderAccessors() public function testHeadersFromStringMultiHeaderWillAggregateLazyLoadedHeaders() { $headers = new Mail\Headers(); - /* @var $pcl \Laminas\Loader\PluginClassLoader */ - $pcl = $headers->getPluginClassLoader(); - $pcl->registerPlugin('foo', GenericMultiHeader::class); - $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()); } @@ -409,40 +406,6 @@ public function testToArrayFormatEncoded() $this->assertEquals($expected, $array); } - 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 - */ - 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();