Skip to content

Commit

Permalink
Simplify IdHeader consumer, don't return comments
Browse files Browse the repository at this point in the history
  • Loading branch information
zbateson committed Sep 30, 2018
1 parent 74d1f88 commit 8d5e605
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 115 deletions.
29 changes: 26 additions & 3 deletions src/Header/AddressHeader.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,33 @@ public function hasAddress($email)
}
return false;
}


/**
* Overridden to return the first email address in the header.
*
* @return string
*/
public function getValue()
{
if (!empty($this->addresses)) {
return $this->addresses[0]->getEmail();
}
return null;
}

/**
* Same as getValue, but for clarity to match AddressPart.
*
* @return string
*/
public function getEmail()
{
return $this->getValue();
}

/**
* Returns the name associated with the first email address (or group) to
* complement getValue()
* Returns the name associated with the first email address to complement
* getValue().
*
* @return string
*/
Expand Down
55 changes: 31 additions & 24 deletions src/Header/Consumer/IdBaseConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,32 @@
*/
namespace ZBateson\MailMimeParser\Header\Consumer;

use Iterator;
use ZBateson\MailMimeParser\Header\Part\CommentPart;

/**
* Serves as a base-consumer for ID headers (like Message-ID and Content-ID).
*
* IdBaseConsumer passes on token processing to its sub-consumer, an
* IdConsumer, and collects Part\LiteralPart objects processed and returned
* by IdConsumer.
* IdBaseConsumer handles invalidly-formatted IDs not within '<' and '>'
* characters. Processing for validly-formatted IDs are passed on to its
* sub-consumer, IdConsumer.
*
* @author Zaahid Bateson
*/
class IdBaseConsumer extends AbstractConsumer
{
/**
* Returns \ZBateson\MailMimeParser\Header\Consumer\IdConsumer as a
* sub-consumer.
*
* Returns the following as sub-consumers:
* - \ZBateson\MailMimeParser\Header\Consumer\CommentConsumer
* - \ZBateson\MailMimeParser\Header\Consumer\QuotedStringConsumer
* - \ZBateson\MailMimeParser\Header\Consumer\IdConsumer
*
* @return AbstractConsumer[] the sub-consumers
*/
protected function getSubConsumers()
{
return [
$this->consumerService->getCommentConsumer(),
$this->consumerService->getQuotedStringConsumer(),
$this->consumerService->getIdConsumer()
];
}
Expand All @@ -43,20 +46,6 @@ protected function getTokenSeparators()
return ['\s+'];
}

/**
* Disables advancing for start tokens not matching '<'.
*
* @param Iterator $tokens
* @param bool $isStartToken
*/
protected function advanceToNextToken(Iterator $tokens, $isStartToken)
{
if ($isStartToken && $tokens->current() !== '<' && $tokens->current() !== '(') {
return;
}
parent::advanceToNextToken($tokens, $isStartToken);
}

/**
* IdBaseConsumer doesn't have start/end tokens, and so always returns
* false.
Expand All @@ -83,8 +72,7 @@ protected function isStartToken($token)
}

/**
* Could be reached by whitespace characters. Returns null to ignore the
* passed token.
* Returns null for whitespace, and LiteralPart for anything else.
*
* @param string $token the token
* @param bool $isLiteral set to true if the token represents a literal -
Expand All @@ -94,6 +82,25 @@ protected function isStartToken($token)
*/
protected function getPartForToken($token, $isLiteral)
{
return null;
if (preg_match('/^\s+$/', $token)) {
return null;
}
return $this->partFactory->newLiteralPart($token);
}

/**
* Overridden to filter out any found CommentPart objects.
*
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts
* @return \ZBateson\MailMimeParser\Header\Part\HeaderPart[]
*/
protected function processParts(array $parts)
{
return array_values(array_filter($parts, function ($part) {
if (empty($part) || $part instanceof CommentPart) {
return false;
}
return true;
}));
}
}
51 changes: 8 additions & 43 deletions src/Header/Consumer/IdConsumer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,22 @@
namespace ZBateson\MailMimeParser\Header\Consumer;

/**
* Parses a single ID from an ID header.
*
* Begins consuming greedily on anything except a space, to allow for
* incorrectly-formatted ID headers. Ends consuming only when a '>' character
* is found. This means an incorrectly-formatted header can't have multiple
* IDs, but one surrounded by '<>' chars may contain spaces.
* Parses a single ID from an ID header. Begins consuming on a '<' char, and
* ends on a '>' char.
*
* @author Zaahid Bateson
*/
class IdConsumer extends AbstractConsumer
class IdConsumer extends GenericConsumer
{
/**
* Returns the following as sub-consumers:
* - \ZBateson\MailMimeParser\Header\Consumer\CommentConsumer
* - \ZBateson\MailMimeParser\Header\Consumer\QuotedStringConsumer
*
* @return AbstractConsumer[] the sub-consumers
*/
protected function getSubConsumers()
{
return [
$this->consumerService->getCommentConsumer(),
$this->consumerService->getQuotedStringConsumer(),
];
}

/**
* Overridden to return patterns matching the beginning part of an ID ("<"
* and ">\s*" chars).
* Overridden to return patterns matching the beginning part of an ID ('<'
* and '>' chars).
*
* @return string[] the patterns
*/
public function getTokenSeparators()
{
return ['<', '>'];
return ['\s+', '<', '>'];
}

/**
Expand All @@ -53,29 +34,13 @@ protected function isEndToken($token)
}

/**
* AddressConsumer is "greedy", so this always returns true unless the token
* consists only of whitespace (as it would between '>' and '<' chars).
* Returns true for '<'.
*
* @param string $token
* @return boolean false
*/
protected function isStartToken($token)
{
return (preg_match('/^\s+$/', $token) !== 1);
}

/**
* Concatenates the passed parts into a single part and returns it.
*
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts
* @return \ZBateson\MailMimeParser\Header\Part\HeaderPart[]
*/
protected function processParts(array $parts)
{
$strValue = '';
foreach ($parts as $part) {
$strValue .= $part->getValue();
}
return [$this->partFactory->newLiteralPart($strValue)];
return ($token === '<');
}
}
33 changes: 4 additions & 29 deletions src/Header/IdHeader.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
namespace ZBateson\MailMimeParser\Header;

use ZBateson\MailMimeParser\Header\Consumer\ConsumerService;
use ZBateson\MailMimeParser\Header\Consumer\AbstractConsumer;
use ZBateson\MailMimeParser\Header\Part\CommentPart;

/**
* Represents a Content-ID, Message-ID, In-Reply-To or References header.
Expand All @@ -21,11 +19,6 @@
*/
class IdHeader extends GenericHeader
{
/**
* @var string[] an array of ids found.
*/
protected $ids = [];

/**
* Returns an IdBaseConsumer.
*
Expand All @@ -38,31 +31,13 @@ protected function getConsumer(ConsumerService $consumerService)
}

/**
* Overridden to extract all IDs into ids array.
*
* @param AbstractConsumer $consumer
*/
protected function setParseHeaderValue(AbstractConsumer $consumer)
{
parent::setParseHeaderValue($consumer);
foreach ($this->parts as $part) {
if (!($part instanceof CommentPart)) {
$this->ids[] = $part->getValue();
}
}
}

/**
* Returns the first parsed ID or null if none exist.
* Synonym for getValue().
*
* @return string|null
*/
public function getValue()
public function getId()
{
if (!empty($this->ids)) {
return $this->ids[0];
}
return null;
return $this->getValue();
}

/**
Expand All @@ -73,6 +48,6 @@ public function getValue()
*/
public function getIds()
{
return $this->ids;
return $this->parts;
}
}
20 changes: 7 additions & 13 deletions tests/MailMimeParser/Header/Consumer/IdBaseConsumerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,15 @@ public function testConsumeIdsWithComments()
{
$ret = $this->idBaseConsumer->__invoke('(first) <first-id> (comment) <second-id@asdf> <third-id>');
$this->assertNotEmpty($ret);
$this->assertCount(5, $ret);

$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\CommentPart', $ret[0]);
$this->assertEquals('first', $ret[0]->getComment());

$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[1]);
$this->assertEquals('first-id', $ret[1]->getValue());
$this->assertCount(3, $ret);

$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\CommentPart', $ret[2]);
$this->assertEquals('comment', $ret[2]->getComment());
$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[0]);
$this->assertEquals('first-id', $ret[0]->getValue());

$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[3]);
$this->assertEquals('second-id@asdf', $ret[3]->getValue());
$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[1]);
$this->assertEquals('second-id@asdf', $ret[1]->getValue());

$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[4]);
$this->assertEquals('third-id', $ret[4]->getValue());
$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[2]);
$this->assertEquals('third-id', $ret[2]->getValue());
}
}
2 changes: 1 addition & 1 deletion tests/MailMimeParser/Header/Consumer/IdConsumerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ public function testConsumeIdWithComments()
$this->assertCount(1, $ret);

$this->assertInstanceOf('\ZBateson\MailMimeParser\Header\Part\LiteralPart', $ret[0]);
$this->assertEquals('first quoted', $ret[0]->getValue());
$this->assertEquals('first quoted', $ret[0]->getValue());
}
}
4 changes: 2 additions & 2 deletions tests/MailMimeParser/Header/IdHeaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function testGetIdsWithComments()
public function testGetIdsWithInvalidValue()
{
$header = new IdHeader($this->consumerService, 'In-Reply-To', 'Blah Blah');
$this->assertEquals('Blah Blah', $header->getValue());
$this->assertEquals(['Blah Blah'], $header->getIds());
$this->assertEquals('Blah', $header->getValue());
$this->assertEquals(['Blah', 'Blah'], $header->getIds());
}
}

0 comments on commit 8d5e605

Please sign in to comment.