PartChildrenContainer   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 153
Duplicated Lines 0 %

Test Coverage

Coverage 90%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 21
eloc 36
c 1
b 0
f 0
dl 0
loc 153
ccs 45
cts 50
cp 0.9
rs 10

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getChildren() 0 6 2
A key() 0 3 1
A current() 0 3 1
A offsetExists() 0 3 1
A valid() 0 3 1
A offsetGet() 0 3 2
A offsetUnset() 0 5 2
A __construct() 0 3 1
A rewind() 0 3 1
A next() 0 3 1
A remove() 0 9 3
A offsetSet() 0 11 3
A hasChildren() 0 3 1
A add() 0 10 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 ArrayAccess;
11
use InvalidArgumentException;
12
use RecursiveIterator;
13
14
/**
15
 * Container of IMessagePart items for a parent IMultiPart.
16
 *
17
 * @author Zaahid Bateson
18
 */
19
class PartChildrenContainer implements ArrayAccess, RecursiveIterator
20
{
21
    /**
22
     * @var IMessagePart[] array of child parts of the IMultiPart object that is
23
     *      holding this container.
24
     */
25
    protected array $children;
26
27
    /**
28
     * @var int current key position within $children for iteration.
29
     */
30
    protected $position = 0;
31
32
    /**
33
     * @param IMessagePart[] $children
34
     */
35 110
    public function __construct(array $children = [])
36
    {
37 110
        $this->children = $children;
38
    }
39
40
    /**
41
     * Returns true if the current element is an IMultiPart.  Note that the
42
     * iterator may still be empty.
43
     */
44 71
    public function hasChildren() : bool
45
    {
46 71
        return ($this->current() instanceof IMultiPart);
47
    }
48
49
    /**
50
     * If the current element points to an IMultiPart, its child iterator is
51
     * returned by calling {@see IMultiPart::getChildIterator()}.
52
     *
53
     * @return RecursiveIterator<IMessagePart>|null the iterator
54
     */
55 70
    public function getChildren() : ?RecursiveIterator
56
    {
57 70
        if ($this->current() instanceof IMultiPart) {
58 70
            return $this->current()->getChildIterator();
59
        }
60 1
        return null;
61
    }
62
63
    /**
64
     * @return IMessagePart
65
     */
66 77
    public function current() : mixed
67
    {
68 77
        return $this->offsetGet($this->position);
69
    }
70
71 71
    public function key() : int
72
    {
73 71
        return $this->position;
74
    }
75
76 77
    public function next() : void
77
    {
78 77
        ++$this->position;
79
    }
80
81 104
    public function rewind() : void
82
    {
83 104
        $this->position = 0;
84
    }
85
86 104
    public function valid() : bool
87
    {
88 104
        return $this->offsetExists($this->position);
89
    }
90
91
    /**
92
     * Adds the passed IMessagePart to the container in the passed position.
93
     *
94
     * If position is not passed or null, the part is added to the end, as the
95
     * last child in the container.
96
     *
97
     * @param IMessagePart $part The part to add
98
     * @param int $position An optional index position (0-based) to add the
99
     *        child at.
100
     */
101 76
    public function add(IMessagePart $part, $position = null) : static
102
    {
103 76
        $index = $position ?? \count($this->children);
104 76
        \array_splice(
105 76
            $this->children,
106 76
            $index,
107 76
            0,
108 76
            [$part]
109 76
        );
110 76
        return $this;
111
    }
112
113
    /**
114
     * Removes the passed part, and returns the integer position it occupied.
115
     *
116
     * @param IMessagePart $part The part to remove.
117
     * @return int the 0-based position it previously occupied.
118
     */
119 15
    public function remove(IMessagePart $part) : ?int
120
    {
121 15
        foreach ($this->children as $key => $child) {
122 15
            if ($child === $part) {
123 15
                $this->offsetUnset($key);
124 15
                return $key;
125
            }
126
        }
127
        return null;
128
    }
129
130
    /**
131
     * @param int $offset
132
     */
133 106
    public function offsetExists(mixed $offset) : bool
134
    {
135 106
        return isset($this->children[$offset]);
136
    }
137
138
    /**
139
     * @param int $offset
140
     */
141 78
    public function offsetGet(mixed $offset) : mixed
142
    {
143 78
        return $this->offsetExists($offset) ? $this->children[$offset] : null;
144
    }
145
146
    /**
147
     * @param int $offset
148
     * @param IMessagePart $value
149
     */
150 1
    public function offsetSet(mixed $offset, mixed $value) : void
151
    {
152 1
        if (!$value instanceof IMessagePart) {
153
            throw new InvalidArgumentException(
154
                \get_class($value) . ' is not a ZBateson\MailMimeParser\Message\IMessagePart'
155
            );
156
        }
157 1
        $index = $offset ?? \count($this->children);
158 1
        $this->children[$index] = $value;
159 1
        if ($index < $this->position) {
160
            ++$this->position;
161
        }
162
    }
163
164
    /**
165
     * @param int $offset
166
     */
167 15
    public function offsetUnset($offset) : void
168
    {
169 15
        \array_splice($this->children, $offset, 1);
170 15
        if ($this->position >= $offset) {
171 15
            --$this->position;
172
        }
173
    }
174
}
175