diff --git a/src/Header/HeaderContainer.php b/src/Header/HeaderContainer.php new file mode 100644 index 00000000..990d56c6 --- /dev/null +++ b/src/Header/HeaderContainer.php @@ -0,0 +1,158 @@ +headerFactory = $headerFactory; + } + + /** + * Returns the string in lower-case, and with non-alphanumeric characters + * stripped out. + * + * @param string $header + * @return string + */ + private function getNormalizedHeaderName($header) + { + return preg_replace('/[^a-z0-9]/', '', strtolower($header)); + } + + public function exists($name, $offset = 0) + { + $s = $this->getNormalizedHeaderName($name); + return isset($this->headerMap[$s][$offset]); + } + + /** + * Returns the AbstractHeader object for the header with the given $name + * + * Note that mime headers aren't case sensitive. + * + * @param string $name + * @param int $offset + * @return \ZBateson\MailMimeParser\Header\AbstractHeader + */ + public function get($name, $offset = 0) + { + $s = $this->getNormalizedHeaderName($name); + if (isset($this->headerMap[$s][$offset])) { + return $this->getByIndex($this->headerMap[$s][$offset]); + } + return null; + } + + public function getAll($name) + { + $s = $this->getNormalizedHeaderName($name); + $ret = []; + if (!empty($this->headerMap[$s])) { + foreach ($this->headerMap[$s] as $index) { + $ret[] = $this->getByIndex($index); + } + } + return $ret; + } + + private function getByIndex($index) + { + if (!isset($this->headers[$index])) { + return null; + } + if ($this->headerObjects[$index] === null) { + $this->headerObjects[$index] = $this->headerFactory->newInstance( + $this->headers[$index][0], + $this->headers[$index][1] + ); + } + return $this->headerObjects[$index]; + } + + public function remove($name, $offset = 0) + { + $s = $this->getNormalizedHeaderName($name); + if (isset($this->headerMap[$s][$offset])) { + $index = $this->headerMap[$s][$offset]; + array_splice($this->headerMap[$s], $offset, 1); + unset($this->headers[$index]); + unset($this->headerObjects[$index]); + return true; + } + return false; + } + + public function removeAll($name) + { + $s = $this->getNormalizedHeaderName($name); + if (!empty($this->headerMap[$s])) { + foreach ($this->headerMap[$s] as $i) { + unset($this->headers[$i]); + unset($this->headerObjects[$i]); + } + $this->headerMap[$s] = []; + return true; + } + return false; + } + + public function add($name, $value) + { + $s = $this->getNormalizedHeaderName($name); + $this->headers[$this->nextIndex] = [ $name, $value ]; + $this->headerObjects[$this->nextIndex] = null; + if (!isset($this->headerMap[$s])) { + $this->headerMap[$s] = []; + } + array_push($this->headerMap[$s], $this->nextIndex); + $this->nextIndex++; + } + + public function set($name, $value, $offset = 0) + { + $s = $this->getNormalizedHeaderName($name); + if (!isset($this->headerMap[$s][$offset])) { + $this->add($name, $value); + return; + } + $i = $this->headerMap[$s][$offset]; + $this->headers[$i] = [ $name, $value ]; + $this->headerObjects[$i] = null; + } + + public function getHeaders() + { + return array_values(array_filter($this->headers)); + } + + public function getIterator() + { + return new ArrayIterator($this->getHeaders()); + } +} diff --git a/src/Header/HeaderFactory.php b/src/Header/HeaderFactory.php index 885a165d..c4706c9c 100644 --- a/src/Header/HeaderFactory.php +++ b/src/Header/HeaderFactory.php @@ -113,4 +113,14 @@ public function newInstance($name, $value) $class = $this->getClassFor($name); return new $class($this->consumerService, $name, $value); } + + /** + * Creates and returns a HeaderContainer. + * + * @return HeaderContainer; + */ + public function newHeaderContainer() + { + return new HeaderContainer($this); + } } diff --git a/src/Message.php b/src/Message.php index 77142f97..b1c7d3d8 100644 --- a/src/Message.php +++ b/src/Message.php @@ -8,7 +8,6 @@ use GuzzleHttp\Psr7; use Psr\Http\Message\StreamInterface; -use ZBateson\MailMimeParser\Header\HeaderFactory; use ZBateson\MailMimeParser\Message\Helper\MessageHelperService; use ZBateson\MailMimeParser\Message\Part\MimePart; use ZBateson\MailMimeParser\Message\Part\PartBuilder; @@ -37,7 +36,6 @@ class Message extends MimePart * @param PartStreamFilterManager $partStreamFilterManager * @param StreamFactory $streamFactory * @param PartFilterFactory $partFilterFactory - * @param HeaderFactory $headerFactory * @param PartBuilder $partBuilder * @param MessageHelperService $messageHelperService * @param StreamInterface $stream @@ -47,7 +45,6 @@ public function __construct( PartStreamFilterManager $partStreamFilterManager, StreamFactory $streamFactory, PartFilterFactory $partFilterFactory, - HeaderFactory $headerFactory, PartBuilder $partBuilder, MessageHelperService $messageHelperService, StreamInterface $stream = null, @@ -57,7 +54,6 @@ public function __construct( $partStreamFilterManager, $streamFactory, $partFilterFactory, - $headerFactory, $partBuilder, $stream, $contentStream diff --git a/src/Message/MessageFactory.php b/src/Message/MessageFactory.php index 00a36ccd..34a876e4 100644 --- a/src/Message/MessageFactory.php +++ b/src/Message/MessageFactory.php @@ -7,7 +7,6 @@ namespace ZBateson\MailMimeParser\Message; use Psr\Http\Message\StreamInterface; -use ZBateson\MailMimeParser\Header\HeaderFactory; use ZBateson\MailMimeParser\Message; use ZBateson\MailMimeParser\Message\Helper\MessageHelperService; use ZBateson\MailMimeParser\Message\Part\PartBuilder; @@ -31,18 +30,16 @@ class MessageFactory extends MimePartFactory /** * @param StreamFactory $sdf * @param PartStreamFilterManagerFactory $psf - * @param HeaderFactory $hf * @param PartFilterFactory $pf * @param MessageHelperService $mhs */ public function __construct( StreamFactory $sdf, PartStreamFilterManagerFactory $psf, - HeaderFactory $hf, PartFilterFactory $pf, MessageHelperService $mhs ) { - parent::__construct($sdf, $psf, $hf, $pf); + parent::__construct($sdf, $psf, $pf); $this->messageHelperService = $mhs; } @@ -63,7 +60,6 @@ public function newInstance(PartBuilder $partBuilder, StreamInterface $stream = $this->partStreamFilterManagerFactory->newInstance(), $this->streamFactory, $this->partFilterFactory, - $this->headerFactory, $partBuilder, $this->messageHelperService, $stream, diff --git a/src/Message/Part/Factory/MessagePartFactory.php b/src/Message/Part/Factory/MessagePartFactory.php index 6a5bd7e7..cee55b48 100644 --- a/src/Message/Part/Factory/MessagePartFactory.php +++ b/src/Message/Part/Factory/MessagePartFactory.php @@ -8,7 +8,6 @@ use ReflectionClass; use Psr\Http\Message\StreamInterface; -use ZBateson\MailMimeParser\Header\HeaderFactory; use ZBateson\MailMimeParser\Message\Helper\MessageHelperService; use ZBateson\MailMimeParser\Message\PartFilterFactory; use ZBateson\MailMimeParser\Message\Part\PartBuilder; @@ -86,7 +85,6 @@ protected static function getCachedInstance() * * @param StreamFactory $sdf * @param PartStreamFilterManagerFactory $psf - * @param HeaderFactory $hf * @param PartFilterFactory $pf * @param MessageHelperService $mhs * @return MessagePartFactory @@ -94,7 +92,6 @@ protected static function getCachedInstance() public static function getInstance( StreamFactory $sdf, PartStreamFilterManagerFactory $psf, - HeaderFactory $hf = null, PartFilterFactory $pf = null, MessageHelperService $mhs = null ) { diff --git a/src/Message/Part/Factory/MimePartFactory.php b/src/Message/Part/Factory/MimePartFactory.php index 64f880c6..7960e629 100644 --- a/src/Message/Part/Factory/MimePartFactory.php +++ b/src/Message/Part/Factory/MimePartFactory.php @@ -8,7 +8,6 @@ use Psr\Http\Message\StreamInterface; use ZBateson\MailMimeParser\Stream\StreamFactory; -use ZBateson\MailMimeParser\Header\HeaderFactory; use ZBateson\MailMimeParser\Message\PartFilterFactory; use ZBateson\MailMimeParser\Message\Part\MimePart; use ZBateson\MailMimeParser\Message\Part\PartBuilder; @@ -20,11 +19,6 @@ */ class MimePartFactory extends MessagePartFactory { - /** - * @var HeaderFactory an instance used for creating MimePart objects - */ - protected $headerFactory; - /** * @var PartFilterFactory an instance used for creating MimePart objects */ @@ -35,17 +29,14 @@ class MimePartFactory extends MessagePartFactory * * @param StreamFactory $sdf * @param PartStreamFilterManagerFactory $psf - * @param HeaderFactory $hf * @param PartFilterFactory $pf */ public function __construct( StreamFactory $sdf, PartStreamFilterManagerFactory $psf, - HeaderFactory $hf, PartFilterFactory $pf ) { parent::__construct($sdf, $psf); - $this->headerFactory = $hf; $this->partFilterFactory = $pf; } @@ -68,7 +59,6 @@ public function newInstance(PartBuilder $partBuilder, StreamInterface $messageSt $this->partStreamFilterManagerFactory->newInstance(), $this->streamFactory, $this->partFilterFactory, - $this->headerFactory, $partBuilder, $partStream, $contentStream diff --git a/src/Message/Part/Factory/PartBuilderFactory.php b/src/Message/Part/Factory/PartBuilderFactory.php index f4ffd864..09593ddd 100644 --- a/src/Message/Part/Factory/PartBuilderFactory.php +++ b/src/Message/Part/Factory/PartBuilderFactory.php @@ -46,8 +46,8 @@ public function __construct(HeaderFactory $headerFactory) public function newPartBuilder(MessagePartFactory $messagePartFactory) { return new PartBuilder( - $this->headerFactory, - $messagePartFactory + $messagePartFactory, + $this->headerFactory->newHeaderContainer() ); } } diff --git a/src/Message/Part/Factory/PartFactoryService.php b/src/Message/Part/Factory/PartFactoryService.php index fab3e170..477ebdbe 100644 --- a/src/Message/Part/Factory/PartFactoryService.php +++ b/src/Message/Part/Factory/PartFactoryService.php @@ -7,7 +7,6 @@ namespace ZBateson\MailMimeParser\Message\Part\Factory; use ZBateson\MailMimeParser\Stream\StreamFactory; -use ZBateson\MailMimeParser\Header\HeaderFactory; use ZBateson\MailMimeParser\Message\Helper\MessageHelperService; use ZBateson\MailMimeParser\Message\MessageFactory; use ZBateson\MailMimeParser\Message\PartFilterFactory; @@ -20,16 +19,11 @@ */ class PartFactoryService { - /** - * @var HeaderFactory the HeaderFactory object used for created headers - */ - protected $headerFactory; - /** * @var PartFilterFactory the PartFilterFactory instance */ protected $partFilterFactory; - + /** * @var PartStreamFilterManagerFactory the PartStreamFilterManagerFactory * instance @@ -47,20 +41,17 @@ class PartFactoryService protected $messageHelperService; /** - * @param HeaderFactory $headerFactory * @param PartFilterFactory $partFilterFactory * @param StreamFactory $streamFactory * @param PartStreamFilterManagerFactory $partStreamFilterManagerFactory * @param MessageHelperService $messageHelperService */ public function __construct( - HeaderFactory $headerFactory, PartFilterFactory $partFilterFactory, StreamFactory $streamFactory, PartStreamFilterManagerFactory $partStreamFilterManagerFactory, MessageHelperService $messageHelperService ) { - $this->headerFactory = $headerFactory; $this->partFilterFactory = $partFilterFactory; $this->streamFactory = $streamFactory; $this->partStreamFilterManagerFactory = $partStreamFilterManagerFactory; @@ -77,7 +68,6 @@ public function getMessageFactory() return MessageFactory::getInstance( $this->streamFactory, $this->partStreamFilterManagerFactory, - $this->headerFactory, $this->partFilterFactory, $this->messageHelperService ); @@ -93,7 +83,6 @@ public function getMimePartFactory() return MimePartFactory::getInstance( $this->streamFactory, $this->partStreamFilterManagerFactory, - $this->headerFactory, $this->partFilterFactory ); } diff --git a/src/Message/Part/ParentHeaderPart.php b/src/Message/Part/ParentHeaderPart.php index 9e94e88b..4a970a64 100644 --- a/src/Message/Part/ParentHeaderPart.php +++ b/src/Message/Part/ParentHeaderPart.php @@ -11,6 +11,7 @@ use ZBateson\MailMimeParser\Header\ParameterHeader; use ZBateson\MailMimeParser\Stream\StreamFactory; use ZBateson\MailMimeParser\Message\PartFilterFactory; +use ZBateson\MailMimeParser\Header\HeaderContainer; /** * A parent part containing headers. @@ -20,31 +21,14 @@ abstract class ParentHeaderPart extends ParentPart { /** - * @var HeaderFactory the HeaderFactory object used for created headers + * @var HeaderContainer */ - protected $headerFactory; - - /** - * @var string[][] array of headers, with keys set to lower-cased, - * alphanumeric characters of the header's name, and values set to an - * array of 2 elements, the first being the header's original name with - * non-alphanumeric characters and original case, and the second set to - * the header's value. - */ - protected $rawHeaders; - - /** - * @var AbstractHeader[] array of parsed header objects populated on-demand, - * the key is set to the header's name lower-cased, and with - * non-alphanumeric characters removed. - */ - protected $headers; + protected $headerContainer; /** * @param PartStreamFilterManager $partStreamFilterManager * @param StreamFactory $streamFactory * @param PartFilterFactory $partFilterFactory - * @param HeaderFactory $headerFactory * @param PartBuilder $partBuilder * @param StreamInterface $stream * @param StreamInterface $contentStream @@ -53,7 +37,6 @@ public function __construct( PartStreamFilterManager $partStreamFilterManager, StreamFactory $streamFactory, PartFilterFactory $partFilterFactory, - HeaderFactory $headerFactory, PartBuilder $partBuilder, StreamInterface $stream = null, StreamInterface $contentStream = null @@ -66,21 +49,7 @@ public function __construct( $stream, $contentStream ); - $this->headerFactory = $headerFactory; - $this->headers['contenttype'] = $partBuilder->getContentType(); - $this->rawHeaders = $partBuilder->getRawHeaders(); - } - - /** - * Returns the string in lower-case, and with non-alphanumeric characters - * stripped out. - * - * @param string $header - * @return string - */ - private function getNormalizedHeaderName($header) - { - return preg_replace('/[^a-z0-9]/', '', strtolower($header)); + $this->headerContainer = $partBuilder->getHeaderContainer(); } /** @@ -91,19 +60,18 @@ private function getNormalizedHeaderName($header) * @param string $name * @return \ZBateson\MailMimeParser\Header\AbstractHeader */ - public function getHeader($name) + public function getHeader($name, $offset = 0) { - $nameKey = $this->getNormalizedHeaderName($name); - if (isset($this->rawHeaders[$nameKey])) { - if (!isset($this->headers[$nameKey])) { - $this->headers[$nameKey] = $this->headerFactory->newInstance( - $this->rawHeaders[$nameKey][0], - $this->rawHeaders[$nameKey][1] - ); - } - return $this->headers[$nameKey]; - } - return null; + return $this->headerContainer->get($name, $offset); + } + + /** + * + * @param type $name + */ + public function getAllHeadersByName($name) + { + return $this->headerContainer->getAll($name); } /** @@ -114,7 +82,17 @@ public function getHeader($name) */ public function getRawHeaders() { - return array_values($this->rawHeaders); + return $this->headerContainer->getHeaders(); + } + + /** + * + * + * @return \Iterator + */ + public function getRawHeaderIterator() + { + return $this->headerContainer->getIterator(); } /** @@ -167,15 +145,24 @@ public function getHeaderParameter($header, $param, $defaultValue = null) * @param string $name * @param string $value */ - public function setRawHeader($name, $value) + public function setRawHeader($name, $value, $offset = 0) + { + $this->headerContainer->set($name, $value, $offset); + $this->onChange(); + } + + /** + * Adds a header with the given $name and $value. + * + * Creates a new \ZBateson\MailMimeParser\Header\AbstractHeader object and + * registers it as a header. + * + * @param string $name + * @param string $value + */ + public function addRawHeader($name, $value) { - $normalized = $this->getNormalizedHeaderName($name); - $header = $this->headerFactory->newInstance($name, $value); - $this->headers[$normalized] = $header; - $this->rawHeaders[$normalized] = [ - $header->getName(), - $header->getRawValue() - ]; + $this->headerContainer->add($name, $value); $this->onChange(); } @@ -186,8 +173,18 @@ public function setRawHeader($name, $value) */ public function removeHeader($name) { - $normalized = $this->getNormalizedHeaderName($name); - unset($this->headers[$normalized], $this->rawHeaders[$normalized]); + $this->headerContainer->removeAll($name); + $this->onChange(); + } + + /** + * Removes the header with the given name + * + * @param string $name + */ + public function removeSingleHeader($name, $offset = 0) + { + $this->headerContainer->remove($name, $offset); $this->onChange(); } } diff --git a/src/Message/Part/PartBuilder.php b/src/Message/Part/PartBuilder.php index 08002e66..f02637a3 100644 --- a/src/Message/Part/PartBuilder.php +++ b/src/Message/Part/PartBuilder.php @@ -7,7 +7,7 @@ namespace ZBateson\MailMimeParser\Message\Part; use Psr\Http\Message\StreamInterface; -use ZBateson\MailMimeParser\Header\HeaderFactory; +use ZBateson\MailMimeParser\Header\HeaderContainer; use ZBateson\MailMimeParser\Message\Part\Factory\MessagePartFactory; /** @@ -43,12 +43,6 @@ class PartBuilder */ private $streamContentEndPos = 0; - /** - * @var \ZBateson\MailMimeParser\Header\HeaderFactory used to parse a - * Content-Type header when needed. - */ - private $headerFactory; - /** * @var MessagePartFactory the factory * needed for creating the Message or MessagePart for the parsed part. @@ -76,13 +70,9 @@ class PartBuilder private $mimeBoundary = false; /** - * @var string[][] an array of headers on the current part. The key index - * is set to the lower-cased, alphanumeric-only, name of the header - * (after stripping out non-alphanumeric characters, e.g. contenttype) - * and each element containing an array of 2 strings, the first being - * the original name of the header, and the second being the value. + * @var HeaderContainer a container for found and parsed headers. */ - private $headers = []; + private $headerContainer; /** * @var PartBuilder[] an array of children found below this part for a mime @@ -100,25 +90,19 @@ class PartBuilder * $messagePartFactory when constructing the Message and its children. */ private $properties = []; - - /** - * @var \ZBateson\MailMimeParser\Header\ParameterHeader parsed content-type - * header. - */ - private $contentType = null; - + /** * Sets up class dependencies. - * - * @param HeaderFactory $hf + * * @param MessagePartFactory $mpf + * @param HeaderContainer $headerContainer */ public function __construct( - HeaderFactory $hf, - MessagePartFactory $mpf + MessagePartFactory $mpf, + HeaderContainer $headerContainer ) { - $this->headerFactory = $hf; $this->messagePartFactory = $mpf; + $this->headerContainer = $headerContainer; } /** @@ -134,26 +118,17 @@ public function __construct( */ public function addHeader($name, $value) { - $nameKey = preg_replace('/[^a-z0-9]/', '', strtolower($name)); - $this->headers[$nameKey] = [$name, $value]; + $this->headerContainer->add($name, $value); } /** - * Returns the raw headers added to this PartBuilder as an array consisting - * of: - * - * Keys set to the name of the header, in all lowercase, and with non- - * alphanumeric characters removed (e.g. Content-Type becomes contenttype). - * - * The value is an array of two elements. The first is the original header - * name (e.g. Content-Type) and the second is the raw string value of the - * header, e.g. 'text/html; charset=utf8'. + * Returns the HeaderContainer object containing parsed headers. * * @return array */ - public function getRawHeaders() + public function getHeaderContainer() { - return $this->headers; + return $this->headerContainer; } /** @@ -223,8 +198,8 @@ public function getParent() */ public function isMime() { - return (isset($this->headers['contenttype']) - || isset($this->headers['mimeversion'])); + return ($this->headerContainer->exists('Content-Type') || + $this->headerContainer->exists('Mime-Version')); } /** @@ -235,13 +210,7 @@ public function isMime() */ public function getContentType() { - if ($this->contentType === null && isset($this->headers['contenttype'])) { - $this->contentType = $this->headerFactory->newInstance( - 'Content-Type', - $this->headers['contenttype'][1] - ); - } - return $this->contentType; + return $this->headerContainer->get('Content-Type'); } /** diff --git a/src/SimpleDi.php b/src/SimpleDi.php index 349abaa2..c6b3a658 100644 --- a/src/SimpleDi.php +++ b/src/SimpleDi.php @@ -171,7 +171,6 @@ public function getPartFactoryService() { if ($this->partFactoryService === null) { $this->partFactoryService = new PartFactoryService( - $this->getHeaderFactory(), $this->getPartFilterFactory(), $this->getStreamFactory(), $this->getPartStreamFilterManagerFactory(), diff --git a/src/Stream/HeaderStream.php b/src/Stream/HeaderStream.php index 1824e801..540c65eb 100644 --- a/src/Stream/HeaderStream.php +++ b/src/Stream/HeaderStream.php @@ -6,11 +6,12 @@ */ namespace ZBateson\MailMimeParser\Stream; +use ArrayIterator; +use GuzzleHttp\Psr7; +use GuzzleHttp\Psr7\StreamDecoratorTrait; +use Psr\Http\Message\StreamInterface; use ZBateson\MailMimeParser\Message\Part\ParentHeaderPart; use ZBateson\MailMimeParser\Message\Part\MessagePart; -use Psr\Http\Message\StreamInterface; -use GuzzleHttp\Psr7\StreamDecoratorTrait; -use GuzzleHttp\Psr7; /** * Psr7 stream decorator implementation providing a readable stream for a part's @@ -47,18 +48,18 @@ public function __construct(MessagePart $part) * * @return array */ - private function getPartHeadersArray() + private function getPartHeadersIterator() { if ($this->part instanceof ParentHeaderPart) { - return $this->part->getRawHeaders(); + return $this->part->getRawHeaderIterator(); } elseif ($this->part->getParent() !== null && $this->part->getParent()->isMime()) { - return [ + return new ArrayIterator([ [ 'Content-Type', $this->part->getContentType() ], [ 'Content-Disposition', $this->part->getContentDisposition() ], [ 'Content-Transfer-Encoding', $this->part->getContentTransferEncoding() ] - ]; + ]); } - return []; + return new ArrayIterator(); } /** @@ -68,8 +69,7 @@ private function getPartHeadersArray() */ public function writePartHeadersTo(StreamInterface $stream) { - $headers = $this->getPartHeadersArray(); - foreach ($headers as $header) { + foreach ($this->getPartHeadersIterator() as $header) { $stream->write("${header[0]}: ${header[1]}\r\n"); } $stream->write("\r\n"); diff --git a/tests/MailMimeParser/Header/HeaderContainerTest.php b/tests/MailMimeParser/Header/HeaderContainerTest.php new file mode 100644 index 00000000..7089b838 --- /dev/null +++ b/tests/MailMimeParser/Header/HeaderContainerTest.php @@ -0,0 +1,276 @@ +mockHeaderFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderFactory') + ->disableOriginalConstructor() + ->getMock(); + } + + public function testAddExistsGet() + { + $ob = new HeaderContainer($this->mockHeaderFactory); + $ob->add('first', 'value'); + $ob->add('second', 'value'); + + $this->assertTrue($ob->exists('first')); + $this->assertTrue($ob->exists('second')); + $this->assertFalse($ob->exists('third')); + $this->assertFalse($ob->exists('first', 1)); + + $this->mockHeaderFactory + ->expects($this->exactly(2)) + ->method('newInstance') + ->withConsecutive( + [ 'first', 'value' ], + [ 'second', 'value' ] + ) + ->willReturnOnConsecutiveCalls('first-value', 'second-value'); + + $this->assertEquals('first-value', $ob->get('first')); + $this->assertEquals('second-value', $ob->get('second')); + $this->assertEquals('first-value', $ob->get('first', 0)); + $this->assertEquals('first-value', $ob->get('first')); + $this->assertEquals('second-value', $ob->get('second', 0)); + $this->assertEquals('second-value', $ob->get('second')); + + $this->assertNull($ob->get('other')); + $this->assertNull($ob->get('second', 1)); + + $headers = [ [ 'first', 'value' ], [ 'second', 'value' ] ]; + $this->assertEquals($headers, $ob->getHeaders()); + } + + public function testAddExistsGetSameName() + { + $ob = new HeaderContainer($this->mockHeaderFactory); + $ob->add('repeated', 'first'); + $ob->add('repeated', 'second'); + $ob->add('repeated', 'third'); + + $this->assertTrue($ob->exists('repeated')); + $this->assertTrue($ob->exists('repeated', 0)); + $this->assertTrue($ob->exists('repeated', 1)); + $this->assertTrue($ob->exists('repeated', 2)); + $this->assertFalse($ob->exists('repeated', 3)); + $this->assertFalse($ob->exists('something-else')); + + $this->mockHeaderFactory + ->expects($this->exactly(3)) + ->method('newInstance') + ->withConsecutive( + [ 'repeated', 'first' ], + [ 'repeated', 'second' ], + [ 'repeated', 'third' ] + ) + ->willReturnOnConsecutiveCalls('repeated-first', 'repeated-second', 'repeated-third'); + + $this->assertEquals('repeated-first', $ob->get('repeated')); + $this->assertEquals('repeated-first', $ob->get('repeated', 0)); + $this->assertEquals('repeated-second', $ob->get('repeated', 1)); + $this->assertEquals('repeated-third', $ob->get('repeated', 2)); + + $instanceHeaders = [ + 'repeated-first', 'repeated-second', 'repeated-third' + ]; + $this->assertEquals($instanceHeaders, $ob->getAll('repeated')); + + $this->assertNull($ob->get('other')); + $this->assertNull($ob->get('repeated', 3)); + + $headers = [ + [ 'repeated', 'first' ], + [ 'repeated', 'second' ], + [ 'repeated', 'third' ] + ]; + $this->assertEquals($headers, $ob->getHeaders()); + } + + public function testAddSetExistsGet() + { + $ob = new HeaderContainer($this->mockHeaderFactory); + $ob->set('first', 'value'); + $ob->set('second', 'value'); + $ob->set('third', 'value'); + + $ob->add('first', 'second-first'); + $ob->add('second', 'second-second'); + + $ob->set('first', 'updated-value'); + $ob->set('second', 'second-updated-value', 1); + + $this->assertTrue($ob->exists('first')); + $this->assertTrue($ob->exists('first', 1)); + $this->assertTrue($ob->exists('second')); + $this->assertTrue($ob->exists('second', 1)); + $this->assertTrue($ob->exists('third')); + + $this->mockHeaderFactory + ->expects($this->exactly(5)) + ->method('newInstance') + ->withConsecutive( + [ 'first', 'updated-value' ], + [ 'second', 'second-updated-value' ], + [ 'first', 'second-first' ], + [ 'second', 'value' ], + [ 'third', 'value' ] + ) + ->willReturnOnConsecutiveCalls( + 'first-updated-value', + 'second-second-updated-value', + 'second-first-value', + 'second-value', + 'third-value' + ); + + $this->assertEquals('first-updated-value', $ob->get('first')); + $this->assertEquals('second-second-updated-value', $ob->get('second', 1)); + $this->assertEquals('second-first-value', $ob->get('first', 1)); + $this->assertEquals('second-value', $ob->get('second')); + $this->assertEquals('third-value', $ob->get('third')); + + $instanceHeaders = [ + 'first-updated-value', 'second-first-value' + ]; + $this->assertEquals($instanceHeaders, $ob->getAll('first')); + + $headers = [ + [ 'first', 'updated-value' ], + [ 'second', 'value' ], + [ 'third', 'value' ], + [ 'first', 'second-first' ], + [ 'second', 'second-updated-value' ] + ]; + $this->assertEquals($headers, $ob->getHeaders()); + } + + public function testAddRemoveGet() + { + $ob = new HeaderContainer($this->mockHeaderFactory); + $ob->add('first', 'value'); + $ob->add('second', 'value'); + $ob->add('third', 'value'); + + $this->assertTrue($ob->exists('first')); + $this->assertTrue($ob->exists('second')); + $this->assertTrue($ob->exists('third')); + + $ob->remove('first'); + + $this->assertFalse($ob->exists('first')); + $this->assertTrue($ob->exists('second')); + $this->assertTrue($ob->exists('third')); + + $this->mockHeaderFactory + ->expects($this->exactly(3)) + ->method('newInstance') + ->withConsecutive( + [ 'second', 'value' ], + [ 'third', 'value' ], + [ 'second', 'updated' ] + ) + ->willReturnOnConsecutiveCalls('second-value', 'third-value', 'second-updated'); + + $this->assertNull($ob->get('first')); + $this->assertEquals('second-value', $ob->get('second')); + $this->assertEquals('third-value', $ob->get('third')); + $headers = [ + [ 'second', 'value' ], + [ 'third', 'value' ], + ]; + $this->assertEquals($headers, $ob->getHeaders()); + + $ob->remove('second'); + $headers = [ + [ 'third', 'value' ] + ]; + $this->assertNull($ob->get('second')); + $this->assertEquals('third-value', $ob->get('third')); + $this->assertEquals($headers, $ob->getHeaders()); + + $ob->set('second', 'updated'); + $headers = [ + [ 'third', 'value' ], + [ 'second', 'updated' ] + ]; + $this->assertEquals($headers, $ob->getHeaders()); + $this->assertEquals('second-updated', $ob->get('second')); + } + + public function testAddRemoveAllGet() + { + $ob = new HeaderContainer($this->mockHeaderFactory); + $ob->add('first', 'value'); + $ob->add('first', 'second-first'); + $ob->add('second', 'value'); + $ob->add('second', 'second-second'); + $ob->add('second', 'third-second'); + $ob->add('third', 'value'); + + $this->assertTrue($ob->exists('FIRST')); + $this->assertTrue($ob->exists('first', 1)); + $this->assertTrue($ob->exists('second')); + $this->assertTrue($ob->exists('SECOND', 1)); + $this->assertTrue($ob->exists('second', 2)); + $this->assertTrue($ob->exists('third')); + + $ob->remove('FIRST'); + + $this->assertTrue($ob->exists('FiRST')); + $this->assertFalse($ob->exists('fIRst', 1)); + $this->assertTrue($ob->exists('second')); + $this->assertTrue($ob->exists('second', 1)); + $this->assertTrue($ob->exists('second', 2)); + $this->assertTrue($ob->exists('third')); + + $this->mockHeaderFactory + ->expects($this->exactly(3)) + ->method('newInstance') + ->withConsecutive( + [ 'first', 'second-first' ], + [ 'second', 'value' ], + [ 'second', 'third-second' ] + ) + ->willReturnOnConsecutiveCalls('second-first-value', 'second-value', 'second-third-second-value'); + + $this->assertNull($ob->get('first', 1)); + $this->assertEquals('second-first-value', $ob->get('first')); + + $ob->remove('second', 1); + $this->assertTrue($ob->exists('second')); + $this->assertTrue($ob->exists('second', 1)); + $this->assertFalse($ob->exists('second', 2)); + + $this->assertEquals('second-value', $ob->get('second')); + $this->assertEquals('second-third-second-value', $ob->get('second', 1)); + $this->assertNull($ob->get('second', 2)); + + $ob->removeAll('second'); + $this->assertFalse($ob->exists('second')); + + $headers = [ + [ 'first', 'second-first' ], + [ 'third', 'value' ], + ]; + $this->assertEquals($headers, $ob->getHeaders()); + + $ob->set('second', 'new-value', 3); + $headers[] = [ 'second', 'new-value' ]; + $this->assertEquals($headers, $ob->getHeaders()); + } +} diff --git a/tests/MailMimeParser/Header/HeaderFactoryTest.php b/tests/MailMimeParser/Header/HeaderFactoryTest.php index 8556ff99..7a12cbb3 100644 --- a/tests/MailMimeParser/Header/HeaderFactoryTest.php +++ b/tests/MailMimeParser/Header/HeaderFactoryTest.php @@ -103,4 +103,12 @@ public function testParameterHeaderInstance() $this->assertNotEquals('ZBateson\MailMimeParser\Header\ParameterHeader', get_class($header)); } } + + public function testHeaderContainer() + { + $this->assertInstanceOf( + 'ZBateson\MailMimeParser\Header\HeaderContainer', + $this->headerFactory->newHeaderContainer() + ); + } } diff --git a/tests/MailMimeParser/Message/MessageFactoryTest.php b/tests/MailMimeParser/Message/MessageFactoryTest.php index 345c898e..a491ea14 100644 --- a/tests/MailMimeParser/Message/MessageFactoryTest.php +++ b/tests/MailMimeParser/Message/MessageFactoryTest.php @@ -26,10 +26,6 @@ protected function setUp() $mockpsfmfactory = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\Factory\PartStreamFilterManagerFactory') ->disableOriginalConstructor() ->getMock(); - $mockHeaderFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderFactory') - ->disableOriginalConstructor() - ->setMethods(['newInstance']) - ->getMock(); $mockFilterFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Message\PartFilterFactory') ->disableOriginalConstructor() ->getMock(); @@ -43,7 +39,6 @@ protected function setUp() $this->messageFactory = new MessageFactory( $mocksdf, $mockpsfmfactory, - $mockHeaderFactory, $mockFilterFactory, $mockHelperService ); @@ -54,7 +49,7 @@ public function testNewInstance() $partBuilder = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\PartBuilder') ->disableOriginalConstructor() ->getMock(); - + $part = $this->messageFactory->newInstance( $partBuilder, Psr7\stream_for('test') diff --git a/tests/MailMimeParser/Message/Part/Factory/MimePartFactoryTest.php b/tests/MailMimeParser/Message/Part/Factory/MimePartFactoryTest.php index b2443f86..ab38f686 100644 --- a/tests/MailMimeParser/Message/Part/Factory/MimePartFactoryTest.php +++ b/tests/MailMimeParser/Message/Part/Factory/MimePartFactoryTest.php @@ -35,13 +35,10 @@ protected function setUp() ->method('newInstance') ->willReturn($psfm); - $mockHeaderFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderFactory') - ->disableOriginalConstructor() - ->getMock(); $mockFilterFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Message\PartFilterFactory') ->disableOriginalConstructor() ->getMock(); - $this->mimePartFactory = new MimePartFactory($mocksdf, $psfmFactory, $mockHeaderFactory, $mockFilterFactory); + $this->mimePartFactory = new MimePartFactory($mocksdf, $psfmFactory, $mockFilterFactory); } public function testNewInstance() diff --git a/tests/MailMimeParser/Message/Part/MimePartTest.php b/tests/MailMimeParser/Message/Part/MimePartTest.php index 9883c06d..61b3f23a 100644 --- a/tests/MailMimeParser/Message/Part/MimePartTest.php +++ b/tests/MailMimeParser/Message/Part/MimePartTest.php @@ -18,7 +18,6 @@ class MimePartTest extends PHPUnit_Framework_TestCase { private $mockPartStreamFilterManager; - private $mockHeaderFactory; private $mockPartFilterFactory; private $mockStreamFactory; @@ -27,9 +26,6 @@ protected function setUp() $this->mockPartStreamFilterManager = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\PartStreamFilterManager') ->disableOriginalConstructor() ->getMock(); - $this->mockHeaderFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderFactory') - ->disableOriginalConstructor() - ->getMock(); $this->mockPartFilterFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Message\PartFilterFactory') ->disableOriginalConstructor() ->getMock(); @@ -54,9 +50,15 @@ protected function getMockedParameterHeader($name, $value, $parameterValue = nul protected function getMockedPartBuilder() { - return $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\PartBuilder') + $hc = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderContainer') ->disableOriginalConstructor() ->getMock(); + $pb = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\PartBuilder') + ->disableOriginalConstructor() + ->getMock(); + $pb->method('getHeaderContainer') + ->willReturn($hc); + return $pb; } protected function getMockedPartBuilderWithChildren() @@ -95,7 +97,6 @@ private function newMimePart($partBuilder, $stream = null, $contentStream = null $this->mockPartStreamFilterManager, $this->mockStreamFactory, $this->mockPartFilterFactory, - $this->mockHeaderFactory, $partBuilder, $stream, $contentStream @@ -152,20 +153,13 @@ public function testCreateChildrenAndGetParts() public function testSetRawHeaderAndRemoveHeader() { - $hf = $this->mockHeaderFactory; $firstHeader = $this->getMockedParameterHeader('First-Header', 'Value'); $secondHeader = $this->getMockedParameterHeader('Second-Header', 'Second Value'); - $hf->expects($this->exactly(2)) - ->method('newInstance') - ->withConsecutive( - [$firstHeader->getName(), $firstHeader->getValue()], - [$secondHeader->getName(), $secondHeader->getValue()] - ) - ->willReturnOnConsecutiveCalls($firstHeader, $secondHeader); - + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); $ms = Psr7\stream_for('message'); - $part = $this->newMimePart($this->getMockedPartBuilder(), $ms); + $part = $this->newMimePart($pb, $ms); // make sure markAsChanged is called $this->assertSame($ms, $part->getStream()); @@ -175,10 +169,27 @@ public function testSetRawHeaderAndRemoveHeader() ->with($part) ->willReturn('Much success'); - $part->setRawHeader($firstHeader->getName(), $firstHeader->getValue()); + $hc->method('get') + ->willReturnMap([ + [ $firstHeader->getName(), 0, $firstHeader ], + [ $secondHeader->getName(), 0, $secondHeader ] + ]); + $hc->method('getHeaders') + ->willReturn([ + [ $firstHeader->getName(), $firstHeader-> getValue() ], + [ $secondHeader->getName(), $secondHeader-> getValue() ] + ]); + + $hc->expects($this->once()) + ->method('set') + ->with($firstHeader->getName(), $firstHeader->getValue(), 1); + $part->setRawHeader($firstHeader->getName(), $firstHeader->getValue(), 1); $this->assertEquals('Much success', $part->getStream()); - $part->setRawHeader($secondHeader->getName(), $secondHeader->getValue()); + $hc->expects($this->once()) + ->method('add') + ->with($secondHeader->getName(), $secondHeader->getValue()); + $part->addRawHeader($secondHeader->getName(), $secondHeader->getValue()); $this->assertSame($firstHeader, $part->getHeader($firstHeader->getName())); $this->assertSame($secondHeader, $part->getHeader($secondHeader->getName())); $this->assertEquals($firstHeader->getValue(), $part->getHeaderValue($firstHeader->getName())); @@ -187,51 +198,29 @@ public function testSetRawHeaderAndRemoveHeader() $this->assertCount(2, $part->getRawHeaders()); $this->assertEquals([[ 'First-Header', $firstHeader->getRawValue() ], [ 'Second-Header', $secondHeader->getRawValue() ]], $part->getRawHeaders()); + $hc->expects($this->once()) + ->method('removeAll') + ->with('FIRST-header'); $part->removeHeader('FIRST-header'); - $this->assertCount(1, $part->getRawHeaders()); - $this->assertNull($part->getHeader($firstHeader->getName())); - $this->assertNull($part->getHeaderValue($firstHeader->getName())); - $this->assertEquals([[ 'Second-Header', $secondHeader->getRawValue() ]], $part->getRawHeaders()); - } - - public function testHeaderCaseInsensitive() - { - $hf = $this->mockHeaderFactory; - $firstHeader = $this->getMockedParameterHeader('First-Header', 'Value'); - $secondHeader = $this->getMockedParameterHeader('Second-Header', 'Second Value'); - $thirdHeader = $this->getMockedParameterHeader('FIRST-header', 'Third Value'); - - $hf->expects($this->exactly(3)) - ->method('newInstance') - ->withConsecutive( - [$firstHeader->getName(), $firstHeader->getValue()], - [$secondHeader->getName(), $secondHeader->getValue()], - [$thirdHeader->getName(), $thirdHeader->getValue()] - ) - ->willReturnOnConsecutiveCalls($firstHeader, $secondHeader, $thirdHeader); - $part = $this->newMimePart($this->getMockedPartBuilder()); - $part->setRawHeader($firstHeader->getName(), $firstHeader->getValue()); - $part->setRawHeader($secondHeader->getName(), $secondHeader->getValue()); - $part->setRawHeader($thirdHeader->getName(), $thirdHeader->getValue()); - - $this->assertSame($thirdHeader, $part->getHeader('first-header')); - $this->assertSame($secondHeader, $part->getHeader('second-header')); + $hc->expects($this->once()) + ->method('remove') + ->with('First-Header', 0); + $part->removeSingleHeader('First-Header'); } public function testGetHeaderParameter() { - $hf = $this->mockHeaderFactory; $header = $this->getMockedParameterHeader('First-Header', 'Value', 'param-value'); - $hf->expects($this->exactly(1)) - ->method('newInstance') - ->withConsecutive( - [$header->getName(), $header->getValue()] - ) - ->willReturnOnConsecutiveCalls($header); - $part = $this->newMimePart($this->getMockedPartBuilder()); - $part->setRawHeader($header->getName(), $header->getValue()); + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->once()) + ->method('get') + ->with('first-header', 0) + ->willReturn($header); + + $part = $this->newMimePart($pb); $this->assertEquals('param-value', $part->getHeaderParameter('first-header', 'param')); } @@ -371,30 +360,6 @@ public function testAddRemoveAndGetChildParts() ); } - public function testPartBuilderHeaders() - { - $hf = $this->mockHeaderFactory; - $header = $this->getMockedParameterHeader('Content-Type', 'text/plain', 'utf-8'); - - $pb = $this->getMockedPartBuilder(); - $pb->expects($this->once()) - ->method('getContentType') - ->willReturn($header); - $pb->expects($this->once()) - ->method('getRawHeaders') - ->willReturn(['contenttype' => ['Blah', 'Blah']]); - - $hf->expects($this->never()) - ->method('newInstance'); - - $part = $this->newMimePart($pb); - $this->assertSame($header, $part->getHeader('CONTENT-TYPE')); - $this->assertEquals('text/plain', $part->getHeaderValue('content-type')); - $this->assertEquals('utf-8', $part->getHeaderParameter('CONTent-TyPE', 'charset')); - $this->assertEquals('UTF-8', $part->getCharset()); - $this->assertEquals('text/plain', $part->getContentType()); - } - public function testGetFilteredParts() { $part = $this->newMimePart($this->getMockedPartBuilderWithChildren()); @@ -437,79 +402,45 @@ public function testGetUnsetHeader() $this->assertEquals('upside-down', $part->getHeaderValue('blah', 'upside-down')); $this->assertEquals('demigorgon', $part->getHeaderParameter('blah', 'blah', 'demigorgon')); } - - public function testGetHeaderAndHeaderParameter() - { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn(['xheader' => ['X-Header', 'Some Value']]); - - $header = $this->getMockedParameterHeader('meen?', 'habibi', 'kochanie'); - $hf = $this->mockHeaderFactory; - $hf->expects($this->once()) - ->method('newInstance') - ->with('X-Header', 'Some Value') - ->willReturn($header); - $part = $this->newMimePart($pb, Psr7\stream_for('habibi')); - $this->assertEquals($header, $part->getHeader('X-header')); - $this->assertEquals('habibi', $part->getHeaderValue('x-HEADER')); - $this->assertEquals('kochanie', $part->getHeaderParameter('x-header', 'anything')); - } - public function testGetContentDisposition() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contentdisposition' => ['Content-Disposition', 'attachment; filename=bin-bashy.jpg'] - ]); - $header = $this->getMockedParameterHeader('meen?', 'habibi'); - $hf = $this->mockHeaderFactory; - $hf->expects($this->once()) - ->method('newInstance') - ->with('Content-Disposition', 'attachment; filename=bin-bashy.jpg') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->exactly(2)) + ->method('get') + ->with('Content-Disposition', 0) ->willReturn($header); $part = $this->newMimePart($pb, Psr7\stream_for('habibi')); - $this->assertSame($header, $part->getHeader('CONTENT-DISPOSITION')); + $this->assertSame($header, $part->getHeader('Content-Disposition')); $this->assertEquals('habibi', $part->getContentDisposition()); } public function testGetContentTransferEncoding() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttransferencoding' => ['Content-Transfer-Encoding', 'x-uue'] - ]); - $header = $this->getMockedParameterHeader('meen?', 'x-uue'); - $hf = $this->mockHeaderFactory; - $hf->expects($this->once()) - ->method('newInstance') - ->with('Content-Transfer-Encoding', 'x-uue') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->exactly(2)) + ->method('get') + ->with('Content-Transfer-Encoding', 0) ->willReturn($header); $part = $this->newMimePart($pb, Psr7\stream_for('habibi')); - $this->assertSame($header, $part->getHeader('CONTENT-TRANSFER_ENCODING')); + $this->assertSame($header, $part->getHeader('Content-Transfer-Encoding')); $this->assertEquals('x-uuencode', $part->getContentTransferEncoding()); } public function testGetCharset() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Content-Type', 'text/plain; charset=blah'] - ]); - $header = $this->getMockedParameterHeader('content-type', 'text/plain', 'blah'); - $hf = $this->mockHeaderFactory; - $hf->expects($this->once()) - ->method('newInstance') - ->with('Content-Type', 'text/plain; charset=blah') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->once()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); $part = $this->newMimePart($pb); @@ -518,22 +449,16 @@ public function testGetCharset() public function testGetFilename() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Content-Type', 'text/plain; name=blooh'], - 'contentdisposition' => ['Content-Disposition', 'attachment; filename=blah'] - ]); - $header = $this->getMockedParameterHeader('content-type', 'text/plain', 'blooh'); $header2 = $this->getMockedParameterHeader('content-disposition', 'attachment', 'blah'); - $hf = $this->mockHeaderFactory; - $hf->expects($this->exactly(2)) - ->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->exactly(2)) + ->method('get') ->withConsecutive( - ['Content-Type', 'text/plain; name=blooh'], - ['Content-Disposition', 'attachment; filename=blah'] + [ 'Content-Type', 0 ], + [ 'Content-Disposition', 0 ] ) ->willReturnOnConsecutiveCalls($header, $header2); @@ -543,25 +468,22 @@ public function testGetFilename() public function testGetDefaultCharsetForTextPlainAndTextHtml() { - $pbText = $this->getMockedPartBuilder(); - $pbText->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Content-Type', 'text/plain'] - ]); - $pbHtml = $this->getMockedPartBuilder(); - $pbHtml->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Content-Type', 'text/html'] - ]); - $headerText = $this->getMockedParameterHeader('content-type', 'text/plain'); $headerHtml = $this->getMockedParameterHeader('content-type', 'text/html'); - - $hf = $this->mockHeaderFactory; - $hf->expects($this->exactly(2)) - ->method('newInstance') - ->withConsecutive(['Content-Type', 'text/plain'], ['Content-Type', 'text/html']) - ->willReturnOnConsecutiveCalls($headerText, $headerHtml); + + $pbText = $this->getMockedPartBuilder(); + $hc = $pbText->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($headerText); + + $pbHtml = $this->getMockedPartBuilder(); + $hc2 = $pbHtml->getHeaderContainer(); + $hc2->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($headerHtml); $partText = $this->newMimePart($pbText); $partHtml = $this->newMimePart($pbHtml); @@ -572,41 +494,30 @@ public function testGetDefaultCharsetForTextPlainAndTextHtml() public function testGetNullCharsetForNonTextPlainOrHtmlPart() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Content-Type', 'text/rtf'] - ]); - $header = $this->getMockedParameterHeader('content-type', 'text/rtf'); - $hf = $this->mockHeaderFactory; - $hf->expects($this->once()) - ->method('newInstance') - ->with('Content-Type', 'text/rtf') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertNull($part->getCharset()); } public function testUsesTransferEncodingAndCharsetForStreamFilter() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Content-Type', 'text/plain; charset=wingding'], - 'contenttransferencoding' => ['Content-Transfer-Encoding', 'klingon'] - ]); $headerType = $this->getMockedParameterHeader('Content-Type', 'text/plain', 'wingding'); $headerEnc = $this->getMockedParameterHeader('Content-Transfer-Encoding', 'klingon'); - - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->method('get') ->willReturnMap([ - ['Content-Type', 'text/plain; charset=wingding', $headerType], - ['Content-Transfer-Encoding', 'klingon', $headerEnc] + [ 'Content-Type', 0, $headerType ], + [ 'Content-Transfer-Encoding', 0, $headerEnc ] ]); - + $manager = $this->mockPartStreamFilterManager; $manager->expects($this->once()) ->method('getContentStream') @@ -621,17 +532,13 @@ public function testUsesTransferEncodingAndCharsetForStreamFilter() public function testIsTextIsMultiPartForNonTextNonMultipart() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'stuff/blooh'); - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertFalse($part->isMultiPart()); $this->assertFalse($part->isTextPart()); @@ -639,17 +546,13 @@ public function testIsTextIsMultiPartForNonTextNonMultipart() public function testIsTextForTextPlain() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'text/plain'); - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertFalse($part->isMultiPart()); $this->assertTrue($part->isTextPart()); @@ -657,17 +560,13 @@ public function testIsTextForTextPlain() public function testIsTextForTextHtml() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'text/html'); - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertFalse($part->isMultiPart()); $this->assertTrue($part->isTextPart()); @@ -675,21 +574,13 @@ public function testIsTextForTextHtml() public function testIsTextForTextMimeTypeWithCharset() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'text/blah', 'utf-8'); - $header->expects($this->once()) - ->method('getValueFor') - ->with('charset'); - - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertFalse($part->isMultiPart()); $this->assertTrue($part->isTextPart()); @@ -697,21 +588,13 @@ public function testIsTextForTextMimeTypeWithCharset() public function testIsTextForTextMimeTypeWithoutCharset() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'text/blah'); - $header->expects($this->once()) - ->method('getValueFor') - ->with('charset'); - - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertFalse($part->isMultiPart()); $this->assertFalse($part->isTextPart()); @@ -719,17 +602,13 @@ public function testIsTextForTextMimeTypeWithoutCharset() public function testIsMultipartForMultipartRelated() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'multipart/related'); - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertTrue($part->isMultiPart()); $this->assertFalse($part->isTextPart()); @@ -737,17 +616,13 @@ public function testIsMultipartForMultipartRelated() public function testIsMultipartForMultipartAnything() { - $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn([ - 'contenttype' => ['Not', 'Important'] - ]); - $header = $this->getMockedParameterHeader('Content-Type', 'multipart/anything'); - $hf = $this->mockHeaderFactory; - $hf->method('newInstance') + $pb = $this->getMockedPartBuilder(); + $hc = $pb->getHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) ->willReturn($header); - $part = $this->newMimePart($pb); $this->assertTrue($part->isMultiPart()); $this->assertFalse($part->isTextPart()); @@ -755,7 +630,6 @@ public function testIsMultipartForMultipartAnything() public function testGetAllPartsByMimeType() { - $hf = $this->mockHeaderFactory; $pf = $this->mockPartFilterFactory; $filter = $this->getMockBuilder('ZBateson\MailMimeParser\Message\PartFilter') ->disableOriginalConstructor() @@ -776,7 +650,6 @@ public function testGetAllPartsByMimeType() public function testGetPartByMimeType() { - $hf = $this->mockHeaderFactory; $pf = $this->mockPartFilterFactory; $filter = $this->getMockBuilder('ZBateson\MailMimeParser\Message\PartFilter') ->disableOriginalConstructor() @@ -800,7 +673,6 @@ public function testGetPartByMimeType() public function testGetCountOfPartsByMimeType() { - $hf = $this->mockHeaderFactory; $pf = $this->mockPartFilterFactory; $filter = $this->getMockBuilder('ZBateson\MailMimeParser\Message\PartFilter') ->disableOriginalConstructor() diff --git a/tests/MailMimeParser/Message/Part/PartBuilderTest.php b/tests/MailMimeParser/Message/Part/PartBuilderTest.php index 4e121ca3..fdf1ed47 100644 --- a/tests/MailMimeParser/Message/Part/PartBuilderTest.php +++ b/tests/MailMimeParser/Message/Part/PartBuilderTest.php @@ -14,18 +14,20 @@ */ class PartBuilderTest extends PHPUnit_Framework_TestCase { - private $mockHeaderFactory; private $mockMessagePartFactory; - + protected function setUp() { - $this->mockHeaderFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderFactory') + $this->mockMessagePartFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\Factory\MessagePartFactory') ->disableOriginalConstructor() ->setMethods(['newInstance']) ->getMock(); - $this->mockMessagePartFactory = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\Factory\MessagePartFactory') + } + + private function newMockHeaderContainer() + { + return $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderContainer') ->disableOriginalConstructor() - ->setMethods(['newInstance']) ->getMock(); } @@ -40,24 +42,25 @@ public function testCanHaveHeaders() ->with('boundary') ->willReturn('Castle Black'); - $this->mockHeaderFactory - ->expects($this->any()) - ->method('newInstance') - ->willReturn($mockHeader); - $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ); $this->assertTrue($instance->canHaveHeaders()); - + + $hc = $this->newMockHeaderContainer(); $parent = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); + $hc->expects($this->once()) + ->method('add') + ->with('CONTENT-TYPE', 'kookoo-keekee'); + $hc->expects($this->once()) + ->method('get') + ->with('Content-Type') + ->willReturn($mockHeader); $parent->addHeader('CONTENT-TYPE', 'kookoo-keekee'); $parent->addChild($instance); @@ -68,20 +71,17 @@ public function testCanHaveHeaders() public function testAddChildren() { $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ); $children = [ new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ), new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ) ]; foreach ($children as $child) { @@ -94,58 +94,59 @@ public function testAddChildren() public function testAddAndGetRawHeaders() { + $hc = $this->newMockHeaderContainer(); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); + $hc->expects($this->exactly(3)) + ->method('add') + ->withConsecutive( + [ 'Mime-VERSION', '42' ], + [ 'Content-TYPE', 'text/blah; blooh' ], + [ 'X-Northernmost-Castle', 'Castle black' ] + ); $instance->addHeader('Mime-VERSION', '42'); $instance->addHeader('Content-TYPE', 'text/blah; blooh'); $instance->addHeader('X-Northernmost-Castle', 'Castle black'); - - $expectedHeaders = [ - 'mimeversion' => ['Mime-VERSION', '42'], - 'contenttype' => ['Content-TYPE', 'text/blah; blooh'], - 'xnorthernmostcastle' => ['X-Northernmost-Castle', 'Castle black'] - ]; - $this->assertEquals($expectedHeaders, $instance->getRawHeaders()); + + $this->assertSame($hc, $instance->getHeaderContainer()); } - public function testAddMimeVersionHeader() + public function testIsMime() { + $hc = $this->newMockHeaderContainer(); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); - $instance->addHeader('Mime-VERSION', '42'); + $hc->expects($this->exactly(5)) + ->method('exists') + ->withConsecutive( + [ 'Content-Type', 0 ], + [ 'Content-Type', 0 ], + [ 'Mime-Version', 0 ], + [ 'Content-Type', 0 ], + [ 'Mime-Version', 0 ] + ) + ->willReturnOnConsecutiveCalls(true, false, true, false, false); + $this->assertTrue($instance->isMime()); - } - - public function testAddContentTypeHeaderIsMime() - { - $instance = new PartBuilder( - $this->mockHeaderFactory, - $this->mockMessagePartFactory, - 'euphrates' - ); - $instance->addHeader('CONTENT-TYPE', '42'); $this->assertTrue($instance->isMime()); + $this->assertFalse($instance->isMime()); } public function testGetContentType() { - $this->mockHeaderFactory - ->expects($this->atLeastOnce()) - ->method('newInstance') - ->willReturn(true); - + $hc = $this->newMockHeaderContainer(); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); - $instance->addHeader('CONTENT-TYPE', '42'); + $hc->expects($this->once()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn(true); $this->assertTrue($instance->getContentType()); } @@ -159,18 +160,16 @@ public function testGetMimeBoundary() ->method('getValueFor') ->with('boundary') ->willReturn('Castle Black'); - - $this->mockHeaderFactory - ->expects($this->atLeastOnce()) - ->method('newInstance') - ->willReturn($mockHeader); - + + $hc = $this->newMockHeaderContainer(); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); - $instance->addHeader('CONTENT-TYPE', 'Snow and Ice'); + $hc->expects($this->once()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockHeader); $this->assertEquals('Castle Black', $instance->getMimeBoundary()); } @@ -183,18 +182,17 @@ public function testIsMultiPart() $mockHeader->expects($this->any()) ->method('getValue') ->willReturnOnConsecutiveCalls('multipart/kookoo', 'text/plain'); - - $this->mockHeaderFactory - ->expects($this->atLeastOnce()) - ->method('newInstance') - ->willReturn($mockHeader); - + + $hc = $this->newMockHeaderContainer(); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); - $instance->addHeader('CONTENT-TYPE', 'kookoo-keekee'); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockHeader); + $this->assertTrue($instance->isMultiPart()); $this->assertFalse($instance->isMultiPart()); } @@ -210,18 +208,15 @@ public function testSetEndBoundaryFound() ->with('boundary') ->willReturn('Castle Black'); - $this->mockHeaderFactory - ->expects($this->any()) - ->method('newInstance') - ->willReturnOnConsecutiveCalls($mockHeader); - + $hc = $this->newMockHeaderContainer(); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); - - $instance->addHeader('CONTENT-TYPE', 'kookoo-keekee'); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockHeader); $this->assertFalse($instance->isParentBoundaryFound()); $this->assertFalse($instance->setEndBoundaryFound('Somewhere... obvs not Castle Black')); @@ -231,9 +226,8 @@ public function testSetEndBoundaryFound() $this->assertTrue($instance->setEndBoundaryFound('--Castle Black--')); $child = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'tigris' + $this->newMockHeaderContainer() ); $instance->addChild($child); $this->assertEquals($instance, $child->getParent()); @@ -260,27 +254,28 @@ public function testSetEndBoundaryFoundWithParent() ->method('getValueFor') ->with('boundary') ->willReturn(null); - - $this->mockHeaderFactory - ->expects($this->atLeastOnce()) - ->method('newInstance') - ->willReturnOnConsecutiveCalls($mockHeader, $mockParentHeader); - + + $hc = $this->newMockHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockHeader); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); + + $hcp = $this->newMockHeaderContainer(); + $hcp->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockParentHeader); $parent = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hcp ); $parent->addChild($instance); - $instance->addHeader('CONTENT-TYPE', 'kookoo-keekee'); - $parent->addHeader('CONTENT-TYPE', 'keekee-kookoo'); - $this->assertSame($parent, $instance->getParent()); $this->assertFalse($instance->isParentBoundaryFound()); $this->assertFalse($instance->setEndBoundaryFound('Somewhere... obvs not Castle Black')); @@ -309,26 +304,27 @@ public function testSetEof() ->with('boundary') ->willReturn(null); - $this->mockHeaderFactory - ->expects($this->atLeastOnce()) - ->method('newInstance') - ->willReturnOnConsecutiveCalls($mockHeader, $mockParentHeader); - + $hc = $this->newMockHeaderContainer(); + $hc->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockHeader); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hc ); + + $hcp = $this->newMockHeaderContainer(); + $hcp->expects($this->atLeastOnce()) + ->method('get') + ->with('Content-Type', 0) + ->willReturn($mockParentHeader); $parent = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $hcp ); $parent->addChild($instance); - $instance->addHeader('CONTENT-TYPE', 'kookoo-keekee'); - $parent->addHeader('CONTENT-TYPE', 'keekee-kookoo'); - $this->assertSame($parent, $instance->getParent()); $this->assertFalse($instance->isParentBoundaryFound()); $this->assertFalse($instance->setEndBoundaryFound('Somewhere... obvs not Castle Black')); @@ -343,9 +339,8 @@ public function testSetEof() public function testSetStreamPartPosAndGetFilename() { $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ); $instance->setStreamPartStartPos(42); $instance->setStreamPartEndPos(84); @@ -356,9 +351,8 @@ public function testSetStreamPartPosAndGetFilename() public function testSetStreamContentPosAndGetFilename() { $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'tigris' + $this->newMockHeaderContainer() ); $instance->setStreamPartStartPos(11); $instance->setStreamContentStartPos(42); @@ -372,19 +366,16 @@ public function testSetStreamContentPosAndGetFilename() public function testSetStreamContentPosAndGetFilenameWithParent() { $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'tigris' + $this->newMockHeaderContainer() ); $parent = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ); $super = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'vistula' + $this->newMockHeaderContainer() ); $parent->addChild($instance); $super->addChild($parent); @@ -420,9 +411,8 @@ public function testSetStreamContentPosAndGetFilenameWithParent() public function testSetAndGetProperties() { $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ); $instance->setProperty('island', 'Westeros'); $instance->setProperty('capital', 'King\'s Landing'); @@ -435,9 +425,8 @@ public function testCreateMessagePart() { $stream = Psr7\stream_for('thingsnstuff'); $instance = new PartBuilder( - $this->mockHeaderFactory, $this->mockMessagePartFactory, - 'euphrates' + $this->newMockHeaderContainer() ); $this->mockMessagePartFactory->expects($this->once()) diff --git a/tests/MailMimeParser/MessageTest.php b/tests/MailMimeParser/MessageTest.php index aa710e3e..6687f2c9 100644 --- a/tests/MailMimeParser/MessageTest.php +++ b/tests/MailMimeParser/MessageTest.php @@ -57,9 +57,15 @@ protected function getMockedParameterHeader($name, $value, $parameterValue = nul protected function getMockedPartBuilder() { - return $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\PartBuilder') + $hc = $this->getMockBuilder('ZBateson\MailMimeParser\Header\HeaderContainer') ->disableOriginalConstructor() ->getMock(); + $pb = $this->getMockBuilder('ZBateson\MailMimeParser\Message\Part\PartBuilder') + ->disableOriginalConstructor() + ->getMock(); + $pb->method('getHeaderContainer') + ->willReturn($hc); + return $pb; } protected function getMockedPartBuilderWithChildren() @@ -124,7 +130,6 @@ private function newMessage($partBuilder, $stream = null, $contentStream = null) $this->mockPartStreamFilterManager, $this->mockStreamFactory, $this->mockPartFilterFactory, - $this->mockHeaderFactory, $partBuilder, $this->mockMessageHelperService, $stream, @@ -311,14 +316,14 @@ public function testIsNotMime() public function testIsMimeWithContentType() { - $hf = $this->mockHeaderFactory; - $header = $this->getMockedParameterHeader('Content-Type', 'text/plain', 'utf-8'); + $header = $this->getMockedParameterHeader('Content-Type', 'text/html', 'utf-8'); $pb = $this->getMockedPartBuilder(); $pb->method('getContentType') ->willReturn($header); - $pb->method('getRawHeaders') - ->willReturn(['contenttype' => ['Blah', 'Blah']]); + $hc = $pb->getHeaderContainer(); + $hc->method('get') + ->willReturnMap([ [ 'Content-Type', 0, $header ] ]); $message = $this->newMessage( $pb @@ -334,8 +339,9 @@ public function testIsMimeWithMimeVersion() ->willReturn($header); $pb = $this->getMockedPartBuilder(); - $pb->method('getRawHeaders') - ->willReturn(['mimeversion' => ['Mime-Version', '4.3']]); + $hc = $pb->getHeaderContainer(); + $hc->method('get') + ->willReturnMap([ [ 'Mime-Version', 0, $header ] ]); $message = $this->newMessage( $pb diff --git a/tests/MailMimeParser/Stream/HeaderStreamTest.php b/tests/MailMimeParser/Stream/HeaderStreamTest.php index ab0f1299..7bc68e6b 100644 --- a/tests/MailMimeParser/Stream/HeaderStreamTest.php +++ b/tests/MailMimeParser/Stream/HeaderStreamTest.php @@ -1,6 +1,7 @@ newMockMimePart(); $mimePart->expects($this->once()) - ->method('getRawHeaders') - ->willReturn([ + ->method('getRawHeaderIterator') + ->willReturn(new ArrayIterator([ [ 'First-Header', 'Missed by a long-shot' ], [ 'Second-Header', 'Gooaaaaaaaaal' ] - ]); + ])); $stream = new HeaderStream($mimePart); $this->assertEquals( diff --git a/tests/_data/emails/m0010.txt b/tests/_data/emails/m0010.txt index e353439f..1e27ce56 100644 --- a/tests/_data/emails/m0010.txt +++ b/tests/_data/emails/m0010.txt @@ -12,6 +12,7 @@ X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300 +From: "Should be Ignored" Die Hasen und die Fr=F6sche