Skip to content

Commit c3de5fc

Browse files
committed
Issue #11: Improve the NaryNode.
1 parent 1ce4437 commit c3de5fc

File tree

2 files changed

+47
-21
lines changed

2 files changed

+47
-21
lines changed

spec/drupol/phptree/Node/NaryNodeSpec.php

+8-5
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ public function it_can_have_children()
5555
$child2 = new NaryNode(2);
5656
$child3 = new Node();
5757
$child4 = new Node();
58-
$child5 = new Node();
59-
$child6 = new Node();
60-
$child7 = new Node();
6158

6259
$this
63-
->add($child1, $child2, $child3, $child4, $child5, $child6, $child7);
60+
->add($child1, $child2, $child3, $child4);
6461

6562
$this->degree()->shouldReturn(2);
6663
$this->count()->shouldReturn(4);
64+
65+
$this->shouldThrow(\Exception::class)
66+
->during('add', [new Node()]);
6767
}
6868

6969
public function it_can_throw_an_error_when_capacity_is_invalid()
@@ -72,7 +72,10 @@ public function it_can_throw_an_error_when_capacity_is_invalid()
7272

7373
$this
7474
->capacity()
75-
->shouldReturn(0);
75+
->shouldReturn(-5);
76+
77+
$this->shouldThrow(\Exception::class)
78+
->during('add', [new NaryNode()]);
7679
}
7780

7881
public function it_can_use_a_different_traverser()

src/Node/NaryNode.php

+39-16
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ public function __construct(int $capacity = 0, NodeInterface $parent = null, Tra
2626
{
2727
parent::__construct($parent);
2828

29-
$capacity = 0 > $capacity ?
30-
0 :
31-
$capacity;
32-
3329
$this->storage()->set(
3430
'capacity',
3531
$capacity
@@ -56,18 +52,10 @@ public function add(NodeInterface ...$nodes): NodeInterface
5652
continue;
5753
}
5854

59-
foreach ($this->getTraverser()->traverse($this) as $candidate) {
60-
if (!($candidate instanceof NaryNodeInterface)) {
61-
continue;
62-
}
63-
64-
if ($candidate->degree() >= $candidate->capacity()) {
65-
continue;
66-
}
67-
68-
$candidate->add($node);
69-
70-
break;
55+
if (null !== $parent = $this->findFirstAvailableNode($this)) {
56+
$parent->add($node);
57+
} else {
58+
throw new \Exception('Unable to add the node to the tree.');
7159
}
7260
}
7361

@@ -105,4 +93,39 @@ public function offsetSet($offset, $value)
10593
parent::offsetSet($offset, $value);
10694
}
10795
}
96+
97+
/**
98+
* Find the first available node in the tree.
99+
*
100+
* When adding nodes to a NaryNode based tree, you must traverse the tree
101+
* and find the first node that can be used as a parent for the node to add.
102+
*
103+
* @param \drupol\phptree\Node\NodeInterface $tree
104+
* The base node.
105+
*
106+
* @return null|\drupol\phptree\Node\NodeInterface
107+
* A node, null if none are found.
108+
*/
109+
protected function findFirstAvailableNode(NodeInterface $tree): ?NodeInterface
110+
{
111+
foreach ($this->getTraverser()->traverse($tree) as $candidate) {
112+
if (!($candidate instanceof NaryNodeInterface)) {
113+
continue;
114+
}
115+
116+
$capacity = $candidate->capacity();
117+
118+
if (0 > $capacity) {
119+
continue;
120+
}
121+
122+
if (0 !== $capacity && $candidate->degree() >= $capacity) {
123+
continue;
124+
}
125+
126+
return $candidate;
127+
}
128+
129+
return null;
130+
}
108131
}

0 commit comments

Comments
 (0)