Test Failed
Push — 2.0 ( 9e8731...0b4092 )
by Zaahid
03:06
created

ParserMimePartProxy::ensureLastChildRead()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 4
rs 10
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\Parser\Proxy;
8
9
use ZBateson\MailMimeParser\Header\HeaderConsts;
10
use ZBateson\MailMimeParser\Message\PartHeaderContainer;
11
use ZBateson\MailMimeParser\Parser\IParser;
12
use ZBateson\MailMimeParser\Parser\PartBuilder;
13
14
/**
15
 * A bi-directional parser-to-part proxy for IMimeParts.
16
 *
17
 * @author Zaahid Bateson
18
 */
19
class ParserMimePartProxy extends ParserPartProxy
20
{
21
    /**
22
     * @var PartHeaderContainer The parsed part's headers.
23
     */
24
    protected $headerContainer;
25
26
    /**
27
     * @var boolean set to true once the end boundary of the currently-parsed
28
     *      part is found.
29
     */
30
    protected $endBoundaryFound = false;
31
32
    /**
33
     * @var boolean set to true once a boundary belonging to this parent's part
34
     *      is found.
35
     */
36
    protected $parentBoundaryFound = false;
37
38
    /**
39
     * @var bool|null|string FALSE if not queried for in the content-type
40
     *      header of this part, NULL if the current part does not have a
41
     *      boundary, and otherwise contains the value of the boundary parameter
42
     *      of the content-type header if the part contains one.
43
     */
44
    protected $mimeBoundary = false;
45
46
    /**
47
     * @var bool true once all children of this part have been parsed.
48
     */
49
    protected $allChildrenParsed = false;
50
51
    /**
52
     * @var ParserPartProxy[] Parsed children used as 'first-in-first-out'
53
     *      stack as children are parsed.
54
     */
55
    protected $children = [];
56
57
    /**
58
     * @var ParserPartProxy Reference to the last child added to this part.
59
     */
60
    protected $lastAddedChild = null;
61
62
    public function __construct(
63
        PartHeaderContainer $headerContainer,
64
        PartBuilder $partBuilder,
65
        IParser $childParser,
66
        ParserMimePartProxy $parent = null
67
    ) {
68
        parent::__construct($partBuilder, $childParser, $parent);
69
        $this->headerContainer = $headerContainer;
70
    }
71
72
    /**
73
     * Ensures that the last child added to this part is fully parsed (content
74
     * and children).
75
     */
76
    protected function ensureLastChildParsed()
77
    {
78
        if ($this->lastAddedChild !== null) {
79
            $this->lastAddedChild->parseAll();
80
        }
81
    }
82
83
    /**
84
     * Parses the next child of this part and adds it to the children list.
85
     */
86
    protected function parseNextChild()
87
    {
88
        if ($this->allChildrenParsed) {
89
            return;
90
        }
91
        $this->parseContent();
92
        $this->ensureLastChildParsed();
93
        $next = $this->childParser->parseNextChild($this);
0 ignored issues
show
Bug introduced by
The method parseNextChild() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        /** @scrutinizer ignore-call */ 
94
        $next = $this->childParser->parseNextChild($this);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
94
        if ($next !== null) {
95
            array_push($this->children, $next);
96
            $this->lastAddedChild = $next;
97
        } else {
98
            $this->allChildrenParsed = true;
99
        }
100
    }
101
102
    /**
103
     * Returns the next child part if one exists, removing it from the internal
104
     * list of children, or null otherwise.
105
     *
106
     * @return IMessagePart|null the child part.
0 ignored issues
show
Bug introduced by
The type ZBateson\MailMimeParser\Parser\Proxy\IMessagePart was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
107
     */
108
    public function popNextChild()
109
    {
110
        if (empty($this->children)) {
111
            $this->parseNextChild();
112
        }
113
        $proxy = array_shift($this->children);
114
        return ($proxy !== null) ? $proxy->getPart() : null;
115
    }
116
117
    /**
118
     * Parses all content and children for this part.
119
     */
120
    public function parseAll()
121
    {
122
        $this->parseContent();
123
        $child = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $child is dead and can be removed.
Loading history...
124
        while (!$this->allChildrenParsed) {
125
            $this->parseNextChild();
126
        }
127
    }
128
129
    /**
130
     * Returns this part's PartHeaderContainer.
131
     *
132
     * @return PartHeaderContainer the container
133
     */
134
    public function getHeaderContainer()
135
    {
136
        return $this->headerContainer;
137
    }
138
139
    /**
140
     * Returns a ParameterHeader representing the parsed Content-Type header for
141
     * this part.
142
     *
143
     * @return \ZBateson\MailMimeParser\Header\ParameterHeader
144
     */
145
    public function getContentType()
146
    {
147
        return $this->headerContainer->get(HeaderConsts::CONTENT_TYPE);
148
    }
149
150
    /**
151
     * Returns the parsed boundary parameter of the Content-Type header if set
152
     * for a multipart message part.
153
     *
154
     * @return string
155
     */
156
    public function getMimeBoundary()
157
    {
158
        if ($this->mimeBoundary === false) {
159
            $this->mimeBoundary = null;
160
            $contentType = $this->getContentType();
161
            if ($contentType !== null) {
162
                $this->mimeBoundary = $contentType->getValueFor('boundary');
163
            }
164
        }
165
        return $this->mimeBoundary;
166
    }
167
168
    /**
169
     * Returns true if the passed $line of read input matches this part's mime
170
     * boundary, or any of its parent's mime boundaries for a multipart message.
171
     *
172
     * If the passed $line is the ending boundary for the current part,
173
     * $this->isEndBoundaryFound will return true after.
174
     *
175
     * @param string $line
176
     * @return bool
177
     */
178
    public function setEndBoundaryFound($line)
179
    {
180
        $boundary = $this->getMimeBoundary();
181
        if ($this->parent !== null && $this->parent->setEndBoundaryFound($line)) {
0 ignored issues
show
introduced by
The method setEndBoundaryFound() does not exist on ZBateson\MailMimeParser\...r\Proxy\ParserPartProxy. Maybe you want to declare this class abstract? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

181
        if ($this->parent !== null && $this->parent->/** @scrutinizer ignore-call */ setEndBoundaryFound($line)) {
Loading history...
182
            $this->parentBoundaryFound = true;
183
            return true;
184
        } elseif ($boundary !== null) {
0 ignored issues
show
introduced by
The condition $boundary !== null is always true.
Loading history...
185
            if ($line === "--$boundary--") {
186
                $this->endBoundaryFound = true;
187
                return true;
188
            } elseif ($line === "--$boundary") {
189
                return true;
190
            }
191
        }
192
        return false;
193
    }
194
195
    /**
196
     * Returns true if the parser passed an input line to setEndBoundary that
197
     * matches a parent's mime boundary, and the following input belongs to a
198
     * new part under its parent.
199
     *
200
     * @return bool
201
     */
202
    public function isParentBoundaryFound()
203
    {
204
        return ($this->parentBoundaryFound);
205
    }
206
207
    /**
208
     * Returns true if an end boundary was found for this part.
209
     *
210
     * @return bool
211
     */
212
    public function isEndBoundaryFound()
213
    {
214
        return ($this->endBoundaryFound);
215
    }
216
217
    /**
218
     * Called once EOF is reached while reading content.  The method sets the
219
     * flag used by isParentBoundaryFound() to true on this part and all parent
220
     * parts.
221
     */
222
    public function setEof()
223
    {
224
        $this->parentBoundaryFound = true;
225
        if ($this->parent !== null) {
226
            $this->parent->parentBoundaryFound = true;
227
        }
228
    }
229
}
230