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\HeaderPart; |
10
|
|
|
use ZBateson\MailMimeParser\Header\Part\Token; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* A minimal implementation of AbstractConsumer defining a CommentConsumer and |
14
|
|
|
* QuotedStringConsumer as sub-consumers, and splitting tokens by whitespace. |
15
|
|
|
* |
16
|
|
|
* Note that GenericConsumer should be instantiated with a |
17
|
|
|
* MimeLiteralPartFactory instead of a HeaderPartFactory. Sub-classes may not |
18
|
|
|
* need MimeLiteralPartFactory instances though. |
19
|
|
|
* |
20
|
|
|
* @author Zaahid Bateson |
21
|
|
|
*/ |
22
|
|
|
class GenericConsumer extends AbstractConsumer |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* Returns \ZBateson\MailMimeParser\Header\Consumer\CommentConsumer and |
26
|
|
|
* \ZBateson\MailMimeParser\Header\Consumer\QuotedStringConsumer as |
27
|
|
|
* sub-consumers. |
28
|
|
|
* |
29
|
|
|
* @return AbstractConsumer[] the sub-consumers |
30
|
|
|
*/ |
31
|
|
|
protected function getSubConsumers() |
32
|
|
|
{ |
33
|
|
|
return [ |
34
|
|
|
$this->consumerService->getCommentConsumer(), |
35
|
|
|
$this->consumerService->getQuotedStringConsumer(), |
36
|
|
|
]; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Returns the regex '\s+' (whitespace) pattern matcher as a token marker so |
41
|
|
|
* the header value is split along whitespace characters. GenericConsumer |
42
|
|
|
* filters out whitespace-only tokens from getPartForToken. |
43
|
|
|
* |
44
|
|
|
* The whitespace character delimits mime-encoded parts for decoding. |
45
|
|
|
* |
46
|
|
|
* @return string[] an array of regex pattern matchers |
47
|
|
|
*/ |
48
|
|
|
protected function getTokenSeparators() |
49
|
|
|
{ |
50
|
|
|
return ['\s+']; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* GenericConsumer doesn't have start/end tokens, and so always returns |
55
|
|
|
* false. |
56
|
|
|
* |
57
|
|
|
* @param string $token |
58
|
|
|
* @return boolean false |
59
|
|
|
*/ |
60
|
|
|
protected function isEndToken($token) |
61
|
|
|
{ |
62
|
|
|
return false; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* GenericConsumer doesn't have start/end tokens, and so always returns |
67
|
|
|
* false. |
68
|
|
|
* |
69
|
|
|
* @param string $token |
70
|
|
|
* @return boolean false |
71
|
|
|
*/ |
72
|
|
|
protected function isStartToken($token) |
73
|
|
|
{ |
74
|
|
|
return false; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Returns true if a space should be added based on the passed last and next |
79
|
|
|
* parts. |
80
|
|
|
* |
81
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart $lastPart |
82
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart $nextPart |
83
|
|
|
* @return bool |
84
|
|
|
*/ |
85
|
|
|
private function shouldAddSpace(HeaderPart $nextPart, HeaderPart $lastPart = null) |
86
|
|
|
{ |
87
|
|
|
return ($lastPart !== null && (!$lastPart->ignoreSpacesAfter() || !$nextPart->ignoreSpacesBefore())); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* Adds the passed $spacePart to the $retParts array if it should be added. |
92
|
|
|
* |
93
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart $spacePart |
94
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $retParts |
95
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart $nextPart |
96
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart $lastPart |
97
|
|
|
* @return bool |
98
|
|
|
*/ |
99
|
|
|
private function addSpaceToRetParts(HeaderPart &$spacePart, array &$retParts, HeaderPart $nextPart, HeaderPart $lastPart = null) |
100
|
|
|
{ |
101
|
|
|
if ($this->shouldAddSpace($nextPart, $lastPart)) { |
102
|
|
|
$retParts[] = $spacePart; |
103
|
|
|
$spacePart = null; |
104
|
|
|
return true; |
105
|
|
|
} |
106
|
|
|
return false; |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
/** |
110
|
|
|
* Checks if the passed space part should be added to the returned parts and |
111
|
|
|
* adds it. |
112
|
|
|
* |
113
|
|
|
* Never adds a space if it's the first part, otherwise only add it if |
114
|
|
|
* either part isn't set to ignore the space |
115
|
|
|
* |
116
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts |
117
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $retParts |
118
|
|
|
* @param int $curIndex |
119
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart $spacePart |
120
|
|
|
*/ |
121
|
|
|
private function addSpaces(array $parts, array &$retParts, $curIndex, HeaderPart &$spacePart = null) |
122
|
|
|
{ |
123
|
|
|
if ($spacePart === null || $parts[$curIndex]->getValue() === '') { |
124
|
|
|
return; |
125
|
|
|
} |
126
|
|
|
$lastPart = end($retParts); |
127
|
|
|
$count = count($parts); |
128
|
|
|
for ($j = $curIndex; $j < $count; ++$j) { |
129
|
|
|
$nextPart = $parts[$j]; |
130
|
|
|
if ($this->addSpaceToRetParts($spacePart, $retParts, $nextPart, $lastPart)) { |
|
|
|
|
131
|
|
|
break; |
132
|
|
|
} |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Returns true if the passed HeaderPart is a Token instance and a space. |
138
|
|
|
* |
139
|
|
|
* @param HeaderPart $part |
140
|
|
|
* @return bool |
141
|
|
|
*/ |
142
|
|
|
private function isSpaceToken(HeaderPart $part) |
143
|
|
|
{ |
144
|
|
|
return ($part instanceof Token && $part->isSpace()); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Filters out ignorable spaces between parts in the passed array. |
149
|
|
|
* |
150
|
|
|
* Spaces with parts on either side of it that specify they can be ignored |
151
|
|
|
* are filtered out. filterIgnoredSpaces is called from within |
152
|
|
|
* processParts, and if needed by an implementing class that overrides |
153
|
|
|
* processParts, must be specifically called. |
154
|
|
|
* |
155
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts |
156
|
|
|
* @return \ZBateson\MailMimeParser\Header\Part\HeaderPart[] |
157
|
|
|
*/ |
158
|
|
|
protected function filterIgnoredSpaces(array $parts) |
159
|
|
|
{ |
160
|
|
|
$retParts = []; |
161
|
|
|
$spacePart = null; |
162
|
|
|
$count = count($parts); |
163
|
|
|
for ($i = 0; $i < $count; ++$i) { |
164
|
|
|
$part = $parts[$i]; |
165
|
|
|
if ($this->isSpaceToken($part)) { |
166
|
|
|
$spacePart = $part; |
167
|
|
|
continue; |
168
|
|
|
} |
169
|
|
|
$this->addSpaces($parts, $retParts, $i, $spacePart); |
170
|
|
|
$retParts[] = $part; |
171
|
|
|
} |
172
|
|
|
// ignore trailing spaces |
173
|
|
|
return $retParts; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Overridden to combine all part values into a single string and return it |
178
|
|
|
* as an array with a single element. |
179
|
|
|
* |
180
|
|
|
* @param \ZBateson\MailMimeParser\Header\Part\HeaderPart[] $parts |
181
|
|
|
* @return \ZBateson\MailMimeParser\Header\Part\LiteralPart[]|array |
182
|
|
|
*/ |
183
|
|
|
protected function processParts(array $parts) |
184
|
|
|
{ |
185
|
|
|
$strValue = ''; |
186
|
|
|
$filtered = $this->filterIgnoredSpaces($parts); |
187
|
|
|
foreach ($filtered as $part) { |
188
|
|
|
$strValue .= $part->getValue(); |
189
|
|
|
} |
190
|
|
|
return [$this->partFactory->newLiteralPart($strValue)]; |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTime
object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.