Completed
Push — master ( 702f4a...a4fb40 )
by Zaahid
02:29
created

GenericConsumer::addSpaceToRetParts()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 2
eloc 6
nc 2
nop 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
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)) {
0 ignored issues
show
Security Bug introduced by
It seems like $lastPart defined by end($retParts) on line 126 can also be of type false; however, ZBateson\MailMimeParser\...r::addSpaceToRetParts() does only seem to accept null|object<ZBateson\Mai...Header\Part\HeaderPart>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

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 returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
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