MultiPart   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 155
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 31
eloc 62
c 1
b 0
f 0
dl 0
loc 155
ccs 81
cts 81
cp 1
rs 9.92

18 Methods

Rating   Name   Duplication   Size   Complexity  
A removeAllParts() 0 12 3
A removePart() 0 12 4
A getPartByContentId() 0 6 2
A getChild() 0 6 1
A getPart() 0 6 1
A getAllPartsByMimeType() 0 3 1
A getAllPartsIterator() 0 6 1
A getChildParts() 0 7 2
A getPartCount() 0 3 1
A getAllParts() 0 7 2
A getCountOfPartsByMimeType() 0 3 1
A addChild() 0 8 2
A __construct() 0 8 1
A getErrorBagChildren() 0 3 1
A iteratorFindAt() 0 12 5
A getChildCount() 0 3 1
A getChildIterator() 0 3 1
A getPartByMimeType() 0 3 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 Psr\Log\LoggerInterface;
14
use RecursiveIterator;
15
use RecursiveIteratorIterator;
16
17
/**
18
 * A message part that contains children.
19
 *
20
 * @author Zaahid Bateson
21
 */
22
abstract class MultiPart extends MessagePart implements IMultiPart
23
{
24
    /**
25
     * @var PartChildrenContainer child part container
26
     */
27
    protected PartChildrenContainer $partChildrenContainer;
28
29 141
    public function __construct(
30
        LoggerInterface $logger,
31
        PartStreamContainer $streamContainer,
32
        PartChildrenContainer $partChildrenContainer,
33
        ?IMimePart $parent = null
34
    ) {
35 141
        parent::__construct($logger, $streamContainer, $parent);
36 141
        $this->partChildrenContainer = $partChildrenContainer;
37
    }
38
39 111
    private function getAllPartsIterator() : AppendIterator
40
    {
41 111
        $iter = new AppendIterator();
42 111
        $iter->append(new ArrayIterator([$this]));
43 111
        $iter->append(new RecursiveIteratorIterator($this->partChildrenContainer, RecursiveIteratorIterator::SELF_FIRST));
44 111
        return $iter;
45
    }
46
47 101
    private function iteratorFindAt(Iterator $iter, int $index, ?callable $fnFilter = null) : ?IMessagePart
48
    {
49 101
        $pos = 0;
50 101
        foreach ($iter as $part) {
51 101
            if (($fnFilter === null || $fnFilter($part))) {
52 101
                if ($index === $pos) {
53 101
                    return $part;
54
                }
55 26
                ++$pos;
56
            }
57
        }
58 18
        return null;
59
    }
60
61 90
    public function getPart(int $index, ?callable $fnFilter = null) : ?IMessagePart
62
    {
63 90
        return $this->iteratorFindAt(
64 90
            $this->getAllPartsIterator(),
65 90
            $index,
66 90
            $fnFilter
67 90
        );
68
    }
69
70 103
    public function getAllParts(?callable $fnFilter = null) : array
71
    {
72 103
        $array = \iterator_to_array($this->getAllPartsIterator(), false);
73 103
        if ($fnFilter !== null) {
74 64
            return \array_values(\array_filter($array, $fnFilter));
75
        }
76 79
        return $array;
77
    }
78
79 4
    public function getPartCount(?callable $fnFilter = null) : int
80
    {
81 4
        return \count($this->getAllParts($fnFilter));
82
    }
83
84 25
    public function getChild(int $index, ?callable $fnFilter = null) : ?IMessagePart
85
    {
86 25
        return $this->iteratorFindAt(
87 25
            $this->partChildrenContainer,
88 25
            $index,
89 25
            $fnFilter
90 25
        );
91
    }
92
93 80
    public function getChildIterator() : RecursiveIterator
94
    {
95 80
        return $this->partChildrenContainer;
96
    }
97
98 103
    public function getChildParts(?callable $fnFilter = null) : array
99
    {
100 103
        $array = \iterator_to_array($this->partChildrenContainer, false);
101 103
        if ($fnFilter !== null) {
102 3
            return \array_values(\array_filter($array, $fnFilter));
103
        }
104 102
        return $array;
105
    }
106
107 99
    public function getChildCount(?callable $fnFilter = null) : int
108
    {
109 99
        return \count($this->getChildParts($fnFilter));
110
    }
111
112 2
    public function getPartByMimeType(string $mimeType, int $index = 0) : ?IMessagePart
113
    {
114 2
        return $this->getPart($index, PartFilter::fromContentType($mimeType));
115
    }
116
117 1
    public function getAllPartsByMimeType(string $mimeType) : array
118
    {
119 1
        return $this->getAllParts(PartFilter::fromContentType($mimeType));
120
    }
121
122 1
    public function getCountOfPartsByMimeType(string $mimeType) : int
123
    {
124 1
        return $this->getPartCount(PartFilter::fromContentType($mimeType));
125
    }
126
127 2
    public function getPartByContentId(string $contentId) : ?IMessagePart
128
    {
129 2
        $sanitized = \preg_replace('/^\s*<|>\s*$/', '', $contentId);
130 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...
131 2
            $cid = $part->getContentId();
132 2
            return ($cid !== null && \strcasecmp($cid, $sanitized) === 0);
133 2
        });
134
    }
135
136 23
    public function addChild(MessagePart $part, ?int $position = null) : static
137
    {
138 23
        if ($part !== $this) {
0 ignored issues
show
introduced by
The condition $part !== $this is always true.
Loading history...
139 23
            $part->parent = $this;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this of type ZBateson\MailMimeParser\Message\MultiPart is incompatible with the declared type ZBateson\MailMimeParser\Message\IMimePart|null of property $parent.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
140 23
            $this->partChildrenContainer->add($part, $position);
141 23
            $this->notify();
142
        }
143 23
        return $this;
144
    }
145
146 20
    public function removePart(IMessagePart $part) : ?int
147
    {
148 20
        $parent = $part->getParent();
149 20
        if ($this !== $parent && $parent !== null) {
150 6
            return $parent->removePart($part);
151
        }
152
153 20
        $position = $this->partChildrenContainer->remove($part);
154 20
        if ($position !== null) {
155 20
            $this->notify();
156
        }
157 20
        return $position;
158
    }
159
160 3
    public function removeAllParts(?callable $fnFilter = null) : int
161
    {
162 3
        $parts = $this->getAllParts($fnFilter);
163 3
        $count = \count($parts);
164 3
        foreach ($parts as $part) {
165 3
            if ($part === $this) {
166 2
                --$count;
167 2
                continue;
168
            }
169 3
            $this->removePart($part);
170
        }
171 3
        return $count;
172
    }
173
174 1
    protected function getErrorBagChildren() : array
175
    {
176 1
        return \array_merge(parent::getErrorBagChildren(), $this->getChildParts());
177
    }
178
}
179