Passed
Push — 2.0 ( df1b1e...20b3e4 )
by Zaahid
08:44 queued 05:27
created

AddressConsumer::processSinglePart()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 13
ccs 10
cts 10
cp 1
rs 9.9666
c 0
b 0
f 0
cc 4
nc 4
nop 3
crap 4
1
<?php
2
/**
3
 * This file is part of the ZBateson\MailMimeParser project.
4
 *
5
 * @license http://opensource.org/licenses/bsd-license.php BSD
6
 */
7
8
namespace ZBateson\MailMimeParser\Header\Consumer;
9
10
use ZBateson\MailMimeParser\Header\Part\AddressGroupPart;
11
use ZBateson\MailMimeParser\Header\Part\AddressPart;
12
use ZBateson\MailMimeParser\Header\Part\CommentPart;
13
use ZBateson\MailMimeParser\Header\Part\LiteralPart;
14
15
/**
16
 * Parses a single part of an address header.
17
 *
18
 * Represents a single part of a list of addresses.  A part could be one email
19
 * address, or one 'group' containing multiple addresses.  The consumer ends on
20
 * finding either a comma token, representing a separation between addresses, or
21
 * a semi-colon token representing the end of a group.
22
 *
23
 * A single email address may consist of just an email, or a name and an email
24
 * address.  Both of these are valid examples of a From header:
25
 *  - From: [email protected]
26
 *  - From: Jon Snow <[email protected]>
27
 *
28
 * Groups must be named, for example:
29
 *  - To: Winterfell: [email protected], Arya Stark <[email protected]>;
30
 *
31
 * Addresses may contain quoted parts and comments, and names may be mime-header
32
 * encoded.
33
 *
34
 * @author Zaahid Bateson
35
 */
36
class AddressConsumer extends AbstractConsumer
37
{
38
    /**
39
     * Returns the following as sub-consumers:
40
     *  - {@see AddressGroupConsumer}
41
     *  - {@see CommentConsumer}
42
     *  - {@see QuotedStringConsumer}
43
     *
44
     * @return AbstractConsumer[] the sub-consumers
45
     */
46 104
    protected function getSubConsumers() : array
47
    {
48 104
        return [
49 104
            $this->consumerService->getAddressGroupConsumer(),
50 104
            $this->consumerService->getAddressEmailConsumer(),
51 104
            $this->consumerService->getCommentConsumer(),
52 104
            $this->consumerService->getQuotedStringConsumer(),
53 104
        ];
54
    }
55
56
    /**
57
     * Overridden to return patterns matching end tokens ("," and ";"), and
58
     * whitespace.
59
     *
60
     * @return string[] the patterns
61
     */
62 104
    public function getTokenSeparators() : array
63
    {
64 104
        return [',', ';', '\s+'];
65
    }
66
67
    /**
68
     * Returns true for commas and semi-colons.
69
     *
70
     * Although the semi-colon is not strictly the end token of an
71
     * AddressConsumer, it could end a parent AddressGroupConsumer.
72
     */
73 104
    protected function isEndToken(string $token) : bool
74
    {
75 104
        return ($token === ',' || $token === ';');
76
    }
77
78
    /**
79
     * AddressConsumer is "greedy", so this always returns true.
80
     */
81 96
    protected function isStartToken(string $token) : bool
82
    {
83 96
        return true;
84
    }
85
86
    /**
87
     * Performs final processing on parsed parts.
88
     *
89
     * AddressConsumer's implementation looks for tokens representing the
90
     * beginning of an address part, to create a Part\AddressPart out of a
91
     * name/address pair, or assign the name part to a parsed
92
     * Part\AddressGroupPart returned from its AddressGroupConsumer
93
     * sub-consumer.
94
     *
95
     * The returned array consists of a single element - either a
96
     * Part\AddressPart or a Part\AddressGroupPart.
97
     *
98
     * @param \ZBateson\MailMimeParser\Header\IHeaderPart[] $parts
99
     * @return \ZBateson\MailMimeParser\Header\IHeaderPart[]|array
100
     */
101 104
    protected function processParts(array $parts) : array
102
    {
103 104
        $strName = '';
104 104
        $strEmail = '';
105 104
        foreach ($parts as $part) {
106 104
            if ($part instanceof AddressGroupPart) {
107 1
                return [
108 1
                    $this->partFactory->newAddressGroupPart(
109 1
                        $part->getAddresses(),
110 1
                        $strName
111 1
                    )
112 1
                ];
113 104
            } elseif ($part instanceof AddressPart) {
114 97
                return [$this->partFactory->newAddressPart($strName, $part->getEmail())];
115 104
            } elseif ((($part instanceof LiteralPart) && !($part instanceof CommentPart)) && $part->getValue() !== '') {
116 56
                $strEmail .= '"' . \preg_replace('/(["\\\])/', '\\\$1', $part->getValue()) . '"';
117
            } else {
118 104
                $strEmail .= \preg_replace('/\s+/', '', $part->getValue());
119
            }
120 104
            $strName .= $part->getValue();
121
        }
122 8
        return [$this->partFactory->newAddressPart('', $strEmail)];
123
    }
124
}
125