Passed
Push — 2.0 ( df1b1e...20b3e4 )
by Zaahid
08:44 queued 05:27
created

PartChildrenContainer   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Test Coverage

Coverage 90%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 22
eloc 38
c 1
b 0
f 0
dl 0
loc 137
ccs 45
cts 50
cp 0.9
rs 10

14 Methods

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