Skip to content

Commit

Permalink
Add 'getHeaderAs' for #140 #142
Browse files Browse the repository at this point in the history
  • Loading branch information
zbateson committed Feb 14, 2023
1 parent 16bd507 commit cbcb000
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 10 deletions.
19 changes: 16 additions & 3 deletions src/Header/HeaderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,27 @@ private function getClassFor(string $name) : string
public function newInstance(string $name, string $value)
{
$class = $this->getClassFor($name);
if (\is_a($class, 'ZBateson\MailMimeParser\Header\MimeEncodedHeader', true)) {
return new $class(
return $this->newInstanceOf($name, $value, $class);
}

/**
* Creates an IHeader instance for the passed header name and value, and
* returns it.
*
* @param string $name The header name.
* @param string $value The header value.
* @return IHeader The created header object.
*/
public function newInstanceOf(string $name, string $value, string $iHeaderClass) : IHeader
{
if (\is_a($iHeaderClass, 'ZBateson\MailMimeParser\Header\MimeEncodedHeader', true)) {
return new $iHeaderClass(
$this->mimeLiteralPartFactory,
$this->consumerService,
$name,
$value
);
}
return new $class($this->consumerService, $name, $value);
return new $iHeaderClass($this->consumerService, $name, $value);
}
}
39 changes: 38 additions & 1 deletion src/Message/IMimePart.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace ZBateson\MailMimeParser\Message;

use ZBateson\MailMimeParser\Header\IHeader;

/**
* An interface representation of any MIME email part.
*
Expand Down Expand Up @@ -36,11 +38,14 @@ public function isSignaturePart();
* If the optional $offset is passed, and multiple headers exist with the
* same name, the one at the passed offset is returned.
*
* Note that mime headers aren't case sensitive, and the '-' character is
* Note that mime header names aren't case sensitive, and the '-' character
* is ignored, so ret
*
* If a header with the given $name and $offset doesn't exist, null is
* returned.
*
* @see IMimePart::getHeaderAs() to parse a header into a provided IHeader
* type and return it.
* @see IMimePart::getHeaderValue() to get the string value portion of a
* specific header only.
* @see IMimePart::getHeaderParameter() to get the string value portion of a
Expand All @@ -60,6 +65,38 @@ public function isSignaturePart();
*/
public function getHeader($name, $offset = 0);

/**
* Returns the IHeader object for the header with the given $name, using the
* passed $iHeaderClass to construct it.
*
* If the optional $offset is passed, and multiple headers exist with the
* same name, the one at the passed offset is returned.
*
* Note that mime headers aren't case sensitive, and the '-' character is
*
* If a header with the given $name and $offset doesn't exist, null is
* returned.
*
* @see IMimePart::getHeaderValue() to get the string value portion of a
* specific header only.
* @see IMimePart::getHeaderParameter() to get the string value portion of a
* specific header's parameter only.
* @see IMimePart::getAllHeaders() to retrieve an array of all header
* objects for this part.
* @see IMimePart::getAllHeadersByName() to retrieve an array of all headers
* with a certain name.
* @see IMimePart::getRawHeaders() to retrieve a two-dimensional string[][]
* array of raw headers in this part.
* @see IMimePart::getRawHeaderIterator() to retrieve an iterator traversing
* a two-dimensional string[] array of raw headers.
* @param string $name The name of the header to retrieve.
* @param
* @param int $offset Optional offset if there are multiple headers with the
* given name.
* @return ?IHeader the header object
*/
public function getHeaderAs(string $name, string $iHeaderClass, int $offset = 0) : ?IHeader;

/**
* Returns an array of all headers in this part.
*
Expand Down
6 changes: 6 additions & 0 deletions src/Message/MimePart.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace ZBateson\MailMimeParser\Message;

use ZBateson\MailMimeParser\Header\HeaderConsts;
use ZBateson\MailMimeParser\Header\IHeader;
use ZBateson\MailMimeParser\Header\ParameterHeader;
use ZBateson\MailMimeParser\IMessage;
use ZBateson\MailMimeParser\MailMimeParser;
Expand Down Expand Up @@ -232,6 +233,11 @@ public function getHeader($name, $offset = 0)
return $this->headerContainer->get($name, $offset);
}

public function getHeaderAs(string $name, string $iHeaderClass, int $offset = 0) : ?IHeader
{
return $this->headerContainer->getAs($name, $iHeaderClass, $offset);
}

public function getAllHeaders()
{
return $this->headerContainer->getHeaderObjects();
Expand Down
48 changes: 47 additions & 1 deletion src/Message/PartHeaderContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use ArrayIterator;
use IteratorAggregate;
use ZBateson\MailMimeParser\Header\HeaderFactory;
use ZBateson\MailMimeParser\Header\IHeader;

/**
* Maintains a collection of headers for a part.
Expand Down Expand Up @@ -120,7 +121,7 @@ private function getAllWithOriginalHeaderNameIfSet(string $name) : ?array
* @param int $offset
* @return \ZBateson\MailMimeParser\Header\IHeader|null
*/
public function get($name, $offset = 0)
public function get(string $name, int $offset = 0)
{
$a = $this->getAllWithOriginalHeaderNameIfSet($name);
if (!empty($a) && isset($a[$offset])) {
Expand All @@ -129,6 +130,29 @@ public function get($name, $offset = 0)
return null;
}

/**
* Returns the IHeader object for the header with the given $name, or null
* if none exist, using the passed $iHeaderClass to construct it.
*
* An optional offset can be provided, which defaults to the first header in
* the collection when more than one header with the same name exists.
*
* Note that mime headers aren't case sensitive.
*
* @param string $name
* @param string $iHeaderClass
* @param int $offset
* @return ?IHeader
*/
public function getAs(string $name, string $iHeaderClass, int $offset = 0) : ?IHeader
{
$a = $this->getAllWithOriginalHeaderNameIfSet($name);
if (!empty($a) && isset($a[$offset])) {
return $this->getByIndexAs($a[$offset], $iHeaderClass);
}
return null;
}

/**
* Returns all headers with the passed name.
*
Expand Down Expand Up @@ -167,6 +191,28 @@ private function getByIndex(int $index)
return $this->headerObjects[$index];
}

/**
* Returns the header in the headers array at the passed 0-based integer
* index or null if one doesn't exist, using the passed $iHeaderClass to
* construct it.
*
* @return \ZBateson\MailMimeParser\Header\IHeader|null
*/
private function getByIndexAs(int $index, string $iHeaderClass) : ?IHeader
{
if (!isset($this->headers[$index])) {
return null;
}
if ($this->headerObjects[$index] !== null && \get_class($this->headerObjects[$index]) === $iHeaderClass) {
return $this->headerObjects[$index];
}
return $this->headerFactory->newInstanceOf(
$this->headers[$index][0],
$this->headers[$index][1],
$iHeaderClass
);
}

/**
* Removes the header from the collection with the passed name. Defaults to
* removing the first instance of the header for a collection that contains
Expand Down
10 changes: 10 additions & 0 deletions tests/MailMimeParser/Header/HeaderFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,14 @@ public function testReceivedHeaderInstance() : void
$this->assertNotInstanceOf(\ZBateson\MailMimeParser\Header\ReceivedHeader::class, $header);
}
}

public function testNewInstanceOf() : void
{
$aHeaders = ['Subject', 'X-Subject', 'From'];
foreach ($aHeaders as $name) {
$header = $this->headerFactory->newInstanceOf($name, 'Test', \ZBateson\MailMimeParser\Header\ReceivedHeader::class);
$this->assertNotNull($header);
$this->assertInstanceOf(\ZBateson\MailMimeParser\Header\ReceivedHeader::class, $header);
}
}
}
16 changes: 16 additions & 0 deletions tests/MailMimeParser/Message/MimePartTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,22 @@ public function testGetHeader() : void
$this->assertEquals('giggidysekint', $part->getHeader('sekint', 1));
}

public function testGetHeaderAs() : void
{
$part = $this->getMimePart();
$oRet = $this->getMockForAbstractClass(\ZBateson\MailMimeParser\Header\IHeader::class);
$oRet2 = $this->getMockForAbstractClass(\ZBateson\MailMimeParser\Header\IHeader::class);
$this->mockHeaderContainer
->expects($this->exactly(2))
->method('getAs')
->withConsecutive(
['foist', 'IHeaderClass', 0],
['sekint', 'IHeaderClass', 1]
)->willReturnOnConsecutiveCalls($oRet, $oRet2);
$this->assertEquals($oRet, $part->getHeaderAs('foist', 'IHeaderClass'));
$this->assertEquals($oRet2, $part->getHeaderAs('sekint', 'IHeaderClass', 1));
}

public function testGetAllHeaders() : void
{
$part = $this->getMimePart();
Expand Down
28 changes: 23 additions & 5 deletions tests/MailMimeParser/Message/PartHeaderContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ protected function setUp() : void
{
$this->mockHeaderFactory = $this->getMockBuilder(\ZBateson\MailMimeParser\Header\HeaderFactory::class)
->disableOriginalConstructor()
->setMethods(['newInstance'])
->setMethods(['newInstance', 'newInstanceOf'])
->getMock();
}

Expand Down Expand Up @@ -162,45 +162,59 @@ public function testAddSetExistsGet() : void
$this->assertEquals($headers, $ob->getHeaders());
}

public function testAddRemoveGet() : void
public function testAddRemoveGetGetAs() : void
{
$ob = new PartHeaderContainer($this->mockHeaderFactory);
$ob->add('first', 'value');
$ob->add('second', 'value');
$ob->add('third', 'value');
$ob->add('fourth', 'value');

$this->assertTrue($ob->exists('first'));
$this->assertTrue($ob->exists('second'));
$this->assertTrue($ob->exists('third'));
$this->assertTrue($ob->exists('fourth'));

$ob->remove('first');

$this->assertFalse($ob->exists('first'));
$this->assertTrue($ob->exists('second'));
$this->assertTrue($ob->exists('third'));
$this->assertTrue($ob->exists('fourth'));

$oRet = $this->getMockForAbstractClass(\ZBateson\MailMimeParser\Header\IHeader::class);
$this->mockHeaderFactory
->expects($this->exactly(3))
->expects($this->exactly(4))
->method('newInstance')
->withConsecutive(
['second', 'value'],
['third', 'value'],
['fourth', 'value'],
['second', 'updated']
)
->willReturnOnConsecutiveCalls('second-value', 'third-value', 'second-updated');
->willReturnOnConsecutiveCalls('second-value', 'third-value', $oRet, 'second-updated');

$custRet = $this->getMockForAbstractClass(\ZBateson\MailMimeParser\Header\IHeader::class);
$this->mockHeaderFactory->expects($this->once())
->method('newInstanceOf')
->with('fourth', 'value', 'IHeaderClass')
->willReturn($custRet);

$this->assertNull($ob->get('first'));
$this->assertEquals('second-value', $ob->get('second'));
$this->assertEquals('third-value', $ob->get('third'));
$this->assertEquals($oRet, $ob->get('fourth'));
$headers = [
['second', 'value'],
['third', 'value'],
['fourth', 'value'],
];
$this->assertEquals($headers, $ob->getHeaders());

$ob->remove('second');
$headers = [
['third', 'value']
['third', 'value'],
['fourth', 'value']
];
$this->assertNull($ob->get('second'));
$this->assertEquals('third-value', $ob->get('third'));
Expand All @@ -209,10 +223,14 @@ public function testAddRemoveGet() : void
$ob->set('second', 'updated');
$headers = [
['third', 'value'],
['fourth', 'value'],
['second', 'updated']
];
$this->assertEquals($headers, $ob->getHeaders());
$this->assertEquals('second-updated', $ob->get('second'));

$h = $ob->getAs('fourth', 'IHeaderClass');
$this->assertEquals($custRet, $h);
}

public function testAddRemoveAllGet() : void
Expand Down

0 comments on commit cbcb000

Please sign in to comment.