ChildrenCollection::has()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Bdf\Form\Aggregate\Collection;
4
5
use ArrayIterator;
6
use Bdf\Form\Aggregate\ChildAggregateInterface;
7
use Bdf\Form\Child\ChildInterface;
8
use Countable;
9
use Iterator;
10
use IteratorAggregate;
11
12
/**
13
 * Simple implementation of children collection for handle dependencies order
14
 * When a child is added, all its dependencies are moved to the end of the collection
15
 */
16
final class ChildrenCollection implements Countable, ChildrenCollectionInterface
17
{
18
    /**
19
     * The collection of children
20
     *
21
     * @var ChildInterface[]
22
     */
23
    private $children = [];
24
25
    /**
26
     * Flag to know if the form has view dependencies in its children
27
     *
28
     * @var boolean
29
     */
30
    private $hasViewDependencies = false;
31
32
33
    /**
34
     * ChildrenCollection constructor.
35
     *
36
     * @param ChildInterface[] $children
37
     */
38 262
    public function __construct(array $children = [])
39
    {
40 262
        foreach ($children as $child) {
41 47
            $this->add($child);
42
        }
43 262
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 135
    public function add(ChildInterface $child): void
49
    {
50 135
        $this->addNamed($child->name(), $child);
51 135
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56 33
    public function has(string $name): bool
57
    {
58 33
        return isset($this->children[$name]);
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 3
    public function remove(string $name): bool
65
    {
66 3
        if (!$this->has($name)) {
67 1
            return false;
68
        }
69
70 2
        unset($this->children[$name]);
71
72 2
        return true;
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 23
    public function offsetExists($offset): bool
79
    {
80 23
        return $this->has($offset);
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 69
    public function offsetGet($offset): ChildInterface
87
    {
88 69
        return $this->children[$offset];
89
    }
90
91
    /**
92
     * {@inheritdoc}
93
     */
94 1
    public function offsetSet($offset, $value): void
95
    {
96 1
        $this->add($value);
97 1
    }
98
99
    /**
100
     * {@inheritdoc}
101
     */
102 1
    public function offsetUnset($offset): void
103
    {
104 1
        $this->remove($offset);
105 1
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110 1
    public function count(): int
111
    {
112 1
        return count($this->children);
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 33
    public function getIterator(): Iterator
119
    {
120 33
        return new ArrayIterator($this->children);
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126 79
    public function reverseIterator(): Iterator
127
    {
128 79
        return new ArrayIterator($this->hasViewDependencies ? array_reverse($this->children) : $this->children);
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134 3
    public function forwardIterator(): Iterator
135
    {
136 3
        return new ArrayIterator($this->children);
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 10
    public function all(): array
143
    {
144 10
        return $this->children;
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 251
    public function duplicate(ChildAggregateInterface $newParent): ChildrenCollectionInterface
151
    {
152 251
        $children = [];
153
154 251
        foreach ($this->children as $key => $child) {
155 124
            $children[$key] = $child->setParent($newParent);
156
        }
157
158 251
        $collection = new static();
159
160 251
        $collection->children = $children;
161 251
        $collection->hasViewDependencies = $this->hasViewDependencies;
162
163 251
        return $collection;
164
    }
165
166
    /**
167
     * Add a child to the dependency tree
168
     *
169
     * @param string $name
170
     * @param ChildInterface $child
171
     */
172 135
    private function addNamed($name, ChildInterface $child): void
173
    {
174 135
        $this->children[$name] = $child;
175 135
        $this->orderDependencies($child);
176 135
    }
177
178
    /**
179
     * Order the collection of children by dependencies
180
     *
181
     * @param ChildInterface $child
182
     */
183 135
    private function orderDependencies(ChildInterface $child): void
184
    {
185 135
        if (!$child->dependencies()) {
186 135
            return;
187
        }
188
189 17
        $this->hasViewDependencies = true;
190
191 17
        foreach ($child->dependencies() as $dependency) {
192 17
            if (!$this->has($dependency)) {
193 7
                continue;
194
            }
195
196 11
            $dependantChild = $this->children[$dependency];
197 11
            unset($this->children[$dependency]);
198
199 11
            $this->add($dependantChild);
200
        }
201 17
    }
202
}
203