Passed
Push — master ( 46ed75...ca2387 )
by Zaahid
03:33
created

MultiPart::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 7
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 3
crap 1
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\Message;
9
10
use AppendIterator;
11
use ArrayIterator;
12
use Iterator;
13
use RecursiveIterator;
14
use RecursiveIteratorIterator;
15
16
/**
17
 * A message part that contains children.
18
 *
19
 * @author Zaahid Bateson
20
 */
21
abstract class MultiPart extends MessagePart implements IMultiPart
22
{
23
    /**
24
     * @var PartChildrenContainer child part container
25
     */
26
    protected PartChildrenContainer $partChildrenContainer;
27
28 139
    public function __construct(
29
        ?IMimePart $parent = null,
30
        ?PartStreamContainer $streamContainer = null,
31
        ?PartChildrenContainer $partChildrenContainer = null
32
    ) {
33 139
        parent::__construct($streamContainer, $parent);
34 139
        $this->partChildrenContainer = $partChildrenContainer ?? new PartChildrenContainer();
35
    }
36
37 109
    private function getAllPartsIterator() : AppendIterator
38
    {
39 109
        $iter = new AppendIterator();
40 109
        $iter->append(new ArrayIterator([$this]));
41 109
        $iter->append(new RecursiveIteratorIterator($this->partChildrenContainer, RecursiveIteratorIterator::SELF_FIRST));
42 109
        return $iter;
43
    }
44
45 99
    private function iteratorFindAt(Iterator $iter, $index, $fnFilter = null) : ?IMessagePart
46
    {
47 99
        $pos = 0;
48 99
        foreach ($iter as $part) {
49 99
            if (($fnFilter === null || $fnFilter($part))) {
50 99
                if ($index === $pos) {
51 99
                    return $part;
52
                }
53 26
                ++$pos;
54
            }
55
        }
56 18
        return null;
57
    }
58
59 88
    public function getPart($index, $fnFilter = null) : ?IMessagePart
60
    {
61 88
        return $this->iteratorFindAt(
62 88
            $this->getAllPartsIterator(),
63 88
            $index,
64 88
            $fnFilter
65 88
        );
66
    }
67
68 102
    public function getAllParts($fnFilter = null) : array
69
    {
70 102
        $array = \iterator_to_array($this->getAllPartsIterator(), false);
71 102
        if ($fnFilter !== null) {
72 64
            return \array_values(\array_filter($array, $fnFilter));
73
        }
74 78
        return $array;
75
    }
76
77 4
    public function getPartCount($fnFilter = null) : int
78
    {
79 4
        return \count($this->getAllParts($fnFilter));
80
    }
81
82 25
    public function getChild($index, $fnFilter = null) : ?IMessagePart
83
    {
84 25
        return $this->iteratorFindAt(
85 25
            $this->partChildrenContainer,
86 25
            $index,
87 25
            $fnFilter
88 25
        );
89
    }
90
91 80
    public function getChildIterator() : RecursiveIterator
92
    {
93 80
        return $this->partChildrenContainer;
94
    }
95
96 102
    public function getChildParts($fnFilter = null) : array
97
    {
98 102
        $array = \iterator_to_array($this->partChildrenContainer, false);
99 102
        if ($fnFilter !== null) {
100 3
            return \array_values(\array_filter($array, $fnFilter));
101
        }
102 101
        return $array;
103
    }
104
105 98
    public function getChildCount($fnFilter = null) : int
106
    {
107 98
        return \count($this->getChildParts($fnFilter));
108
    }
109
110 2
    public function getPartByMimeType($mimeType, $index = 0) : ?IMessagePart
111
    {
112 2
        return $this->getPart($index, PartFilter::fromContentType($mimeType));
113
    }
114
115 1
    public function getAllPartsByMimeType($mimeType) : array
116
    {
117 1
        return $this->getAllParts(PartFilter::fromContentType($mimeType));
118
    }
119
120 1
    public function getCountOfPartsByMimeType($mimeType) : int
121
    {
122 1
        return $this->getPartCount(PartFilter::fromContentType($mimeType));
123
    }
124
125 2
    public function getPartByContentId($contentId) : ?IMessagePart
126
    {
127 2
        $sanitized = \preg_replace('/^\s*<|>\s*$/', '', $contentId);
128 2
        return $this->getPart(0, function(IMessagePart $part) use ($sanitized) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
129 2
            $cid = $part->getContentId();
130 2
            return ($cid !== null && \strcasecmp($cid, $sanitized) === 0);
131 2
        });
132
    }
133
134 23
    public function addChild(IMessagePart $part, ?int $position = null) : static
135
    {
136 23
        if ($part !== $this) {
0 ignored issues
show
introduced by
The condition $part !== $this is always true.
Loading history...
137 23
            $part->parent = $this;
0 ignored issues
show
Bug introduced by
Accessing parent on the interface ZBateson\MailMimeParser\Message\IMessagePart suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
138 23
            $this->partChildrenContainer->add($part, $position);
139 23
            $this->notify();
140
        }
141 23
        return $this;
142
    }
143
144 20
    public function removePart(IMessagePart $part) : ?int
145
    {
146 20
        $parent = $part->getParent();
147 20
        if ($this !== $parent && $parent !== null) {
148 6
            return $parent->removePart($part);
149
        }
150
151 20
        $position = $this->partChildrenContainer->remove($part);
152 20
        if ($position !== null) {
153 20
            $this->notify();
154
        }
155 20
        return $position;
156
    }
157
158 3
    public function removeAllParts($fnFilter = null) : int
159
    {
160 3
        $parts = $this->getAllParts($fnFilter);
161 3
        $count = \count($parts);
162 3
        foreach ($parts as $part) {
163 3
            if ($part === $this) {
164 2
                --$count;
165 2
                continue;
166
            }
167 3
            $this->removePart($part);
168
        }
169 3
        return $count;
170
    }
171
172
    protected function getErrorBagChildren() : array
173
    {
174
        return $this->getChildParts();
175
    }
176
}
177