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
|
|
|
namespace ZBateson\MailMimeParser\Header\Consumer; |
8
|
|
|
|
9
|
|
|
use ZBateson\MailMimeParser\Header\Part\Token; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* A minimal implementation of AbstractConsumer defining a CommentConsumer and |
13
|
|
|
* QuotedStringConsumer as sub-consumers, and splitting tokens by whitespace. |
14
|
|
|
* |
15
|
|
|
* @author Zaahid Bateson |
16
|
|
|
*/ |
17
|
|
|
class GenericConsumer extends AbstractConsumer |
18
|
|
|
{ |
19
|
|
|
/** |
20
|
|
|
* Returns \ZBateson\MailMimeParser\Header\Consumer\CommentConsumer and |
21
|
|
|
* \ZBateson\MailMimeParser\Header\Consumer\QuotedStringConsumer as |
22
|
|
|
* sub-consumers. |
23
|
|
|
* |
24
|
|
|
* @return AbstractConsumer[] the sub-consumers |
25
|
|
|
*/ |
26
|
|
|
protected function getSubConsumers() |
27
|
|
|
{ |
28
|
|
|
return [ |
29
|
|
|
$this->consumerService->getCommentConsumer(), |
30
|
|
|
$this->consumerService->getQuotedStringConsumer(), |
31
|
|
|
]; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Returns the regex '\s+' (whitespace) pattern matcher as a token marker so |
36
|
|
|
* the header value is split along whitespace characters. GenericConsumer |
37
|
|
|
* filters out whitespace-only tokens from getPartForToken. |
38
|
|
|
* |
39
|
|
|
* The whitespace character delimits mime-encoded parts for decoding. |
40
|
|
|
* |
41
|
|
|
* @return string[] an array of regex pattern matchers |
42
|
|
|
*/ |
43
|
|
|
protected function getTokenSeparators() |
44
|
|
|
{ |
45
|
|
|
return ['\s+']; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* GenericConsumer doesn't have start/end tokens, and so always returns |
50
|
|
|
* false. |
51
|
|
|
* |
52
|
|
|
* @param string $token |
53
|
|
|
* @return boolean false |
54
|
|
|
*/ |
55
|
|
|
protected function isEndToken($token) |
56
|
|
|
{ |
57
|
|
|
return false; |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* GenericConsumer doesn't have start/end tokens, and so always returns |
62
|
|
|
* false. |
63
|
|
|
* |
64
|
|
|
* @param string $token |
65
|
|
|
* @return boolean false |
66
|
|
|
*/ |
67
|
|
|
protected function isStartToken($token) |
68
|
|
|
{ |
69
|
|
|
return false; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Creates and returns a |
74
|
|
|
* \ZBateson\MailMimeParser\Header\Part\MimeLiteralPart out of the passed |
75
|
|
|
* string token and returns it. |
76
|
|
|
* |
77
|
|
|
* @param string $token |
78
|
|
|
* @param bool $isLiteral |
79
|
|
|
* @return \ZBateson\MailMimeParser\Header\Part\HeaderPart |
80
|
|
|
*/ |
81
|
|
View Code Duplication |
protected function getPartForToken($token, $isLiteral) |
|
|
|
|
82
|
|
|
{ |
83
|
|
|
if (preg_match('/^\s+$/', $token) && !$isLiteral) { |
84
|
|
|
return $this->partFactory->newToken(' '); |
85
|
|
|
} elseif ($isLiteral) { |
86
|
|
|
return $this->partFactory->newLiteralPart($token); |
87
|
|
|
} else { |
88
|
|
|
return $this->partFactory->newMimeLiteralPart($token); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* Checks if the passed space part should be added to the returned parts and |
94
|
|
|
* adds it. |
95
|
|
|
* |
96
|
|
|
* Never adds a space if it's the first part, otherwise only add it if |
97
|
|
|
* either part isn't set to ignore the space |
98
|
|
|
* |
99
|
|
|
* @param array $parts |
100
|
|
|
* @param array $retParts |
101
|
|
|
* @param ZBateson\MailMimeParser\Header\Part\HeaderPart $spacePart |
102
|
|
|
* @param int $curIndex |
103
|
|
|
* @return boolean true if the part was added |
104
|
|
|
*/ |
105
|
|
|
private function checkAddFilteredSpace(array $parts, array &$retParts, &$spacePart, $curIndex) |
106
|
|
|
{ |
107
|
|
|
$lastPart = end($retParts); |
108
|
|
|
$count = count($parts); |
109
|
|
|
for ($j = $curIndex; $j < $count; ++$j) { |
110
|
|
|
$next = $parts[$j]; |
111
|
|
|
if ($lastPart !== null && (!$lastPart->ignoreSpacesAfter() || !$next->ignoreSpacesBefore())) { |
112
|
|
|
$retParts[] = $spacePart; |
113
|
|
|
$spacePart = null; |
114
|
|
|
return true; |
115
|
|
|
} |
116
|
|
|
} |
117
|
|
|
return false; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Filters out ignorable spaces between parts in the passed array. |
122
|
|
|
* |
123
|
|
|
* Spaces with parts on either side of it that specify they can be ignored |
124
|
|
|
* are filtered out. filterIgnoredSpaces is called from within |
125
|
|
|
* processParts, and if needed by an implementing class that overrides |
126
|
|
|
* processParts, must be specifically called. |
127
|
|
|
* |
128
|
|
|
* @param ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts |
129
|
|
|
* @return ZBateson\MailMimeParser\Header\Part\HeaderPart[] |
130
|
|
|
*/ |
131
|
|
|
protected function filterIgnoredSpaces(array $parts) |
132
|
|
|
{ |
133
|
|
|
$retParts = []; |
134
|
|
|
$spacePart = null; |
135
|
|
|
$count = count($parts); |
136
|
|
|
for ($i = 0; $i < $count; ++$i) { |
137
|
|
|
$part = $parts[$i]; |
138
|
|
|
if ($part instanceof Token && $part->isSpace()) { |
139
|
|
|
$spacePart = $part; |
140
|
|
|
continue; |
141
|
|
|
} elseif ($spacePart !== null && $part->getValue() !== '') { |
142
|
|
|
$this->checkAddFilteredSpace($parts, $retParts, $spacePart, $i); |
143
|
|
|
} |
144
|
|
|
$retParts[] = $part; |
145
|
|
|
} |
146
|
|
|
// ignore trailing spaces |
147
|
|
|
return $retParts; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Overridden to combine all part values into a single string and return it |
152
|
|
|
* as an array with a single element. |
153
|
|
|
* |
154
|
|
|
* @param ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts |
155
|
|
|
* @return ZBateson\MailMimeParser\Header\Part\LiteralPart[] |
156
|
|
|
*/ |
157
|
|
|
protected function processParts(array $parts) |
158
|
|
|
{ |
159
|
|
|
$strValue = ''; |
160
|
|
|
$filtered = $this->filterIgnoredSpaces($parts); |
161
|
|
|
foreach ($filtered as $part) { |
162
|
|
|
$strValue .= $part->getValue(); |
163
|
|
|
} |
164
|
|
|
return [$this->partFactory->newLiteralPart($strValue)]; |
|
|
|
|
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.