Skip to content

Commit fd67e47

Browse files
committed
Add NaryNode tree.
1 parent bc78ffb commit fd67e47

20 files changed

+189
-13
lines changed

.php_cs.dist

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ return PhpCsFixer\Config::create()
2020
'declare_equal_normalize' => [
2121
'space' => 'single',
2222
],
23+
'declare_strict_types' => TRUE,
2324
'include' => TRUE,
2425
'is_null' => TRUE,
2526
'linebreak_after_opening_tag' => TRUE,

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"apigen/apigen": "dev-master",
2020
"drupol/phpspec-annotation": "^1.0",
2121
"friendsofphp/php-cs-fixer": "^2.13",
22+
"graphp/graphviz": "^0.2.1",
2223
"infection/infection": "^0.11.2",
2324
"jakub-onderka/php-parallel-lint": "^1.0",
2425
"leanphp/phpspec-code-coverage": "^4",

grumphp.yml.dist

+2-7
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ parameters:
3131
end_point: ~
3232
timeout: ~
3333
run_always: false
34-
composer_require_checker:
35-
composer_file: 'composer.json'
36-
config_file: ~
37-
ignore_parse_errors: false
38-
triggered_by: ['composer.json', 'composer.lock', '*.php']
3934
infection:
40-
min_msi: 90
41-
min_covered_msi: 90
35+
min_msi: 80
36+
min_covered_msi: 80

spec/drupol/phptree/Node/KeyValueNodeSpec.php

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace spec\drupol\phptree\Node;
46

57
use drupol\phptree\Node\KeyValueNode;
@@ -25,4 +27,13 @@ public function it_can_be_set_with_a_key_and_value()
2527
->getValue()
2628
->shouldReturn('root');
2729
}
30+
31+
public function it_can_throw_an_error_when_capacity_is_invalid()
32+
{
33+
$this->beConstructedWith(-5);
34+
35+
$this
36+
->capacity()
37+
->shouldReturn(0);
38+
}
2839
}
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace spec\drupol\phptree\Node;
6+
7+
use drupol\phptree\Node\NaryNode;
8+
use PhpSpec\ObjectBehavior;
9+
10+
class NaryNodeSpec extends ObjectBehavior
11+
{
12+
public function it_is_initializable()
13+
{
14+
$this->shouldHaveType(NaryNode::class);
15+
}
16+
17+
public function it_can_get_the_capacity()
18+
{
19+
$this
20+
->capacity()
21+
->shouldReturn(0);
22+
}
23+
24+
public function it_can_get_the_capacity_when_using_a_custom_capacity()
25+
{
26+
$this->beConstructedWith(3);
27+
28+
$this
29+
->capacity()
30+
->shouldReturn(3);
31+
}
32+
33+
public function it_can_throw_an_error_when_capacity_is_invalid()
34+
{
35+
$this->beConstructedWith(-5);
36+
37+
$this
38+
->capacity()
39+
->shouldReturn(0);
40+
}
41+
42+
public function it_can_be_counted()
43+
{
44+
$this->beConstructedWith(2);
45+
46+
foreach (\range('A', 'Z') as $value) {
47+
$node = new NaryNode(2);
48+
49+
$this->add($node);
50+
}
51+
52+
$this
53+
->count()
54+
->shouldReturn(26);
55+
}
56+
}

spec/drupol/phptree/Node/NodeSpec.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace spec\drupol\phptree\Node;
46

57
use drupol\phptree\Node\Node;

spec/drupol/phptree/Node/ValueNodeSpec.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace spec\drupol\phptree\Node;
46

57
use drupol\phptree\Node\ValueNode;

spec/drupol/phptree/Visitor/BreadthFirstVisitorSpec.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace spec\drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\Node;

spec/drupol/phptree/Visitor/PostOrderVisitorSpec.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace spec\drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\Node;

spec/drupol/phptree/Visitor/PreOrderVisitorSpec.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace spec\drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\Node;

src/Node/KeyValueNode.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ class KeyValueNode extends ValueNode implements KeyValueNodeInterface
2121
*
2222
* @param mixed|null $key
2323
* @param mixed|null $value
24+
* @param int $capacity
2425
* @param \drupol\phptree\Node\NodeInterface|NULL $parent
2526
*/
26-
public function __construct($key = null, $value = null, NodeInterface $parent = null)
27+
public function __construct($key = null, $value = null, int $capacity = 0, NodeInterface $parent = null)
2728
{
28-
parent::__construct($value, $parent);
29+
parent::__construct($value, $capacity, $parent);
2930

3031
$this->key = $key;
3132
}

src/Node/NaryNode.php

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace drupol\phptree\Node;
6+
7+
use drupol\phptree\Visitor\BreadthFirstVisitor;
8+
9+
/**
10+
* Class NaryNode
11+
*/
12+
class NaryNode extends Node
13+
{
14+
/**
15+
* @var int
16+
*/
17+
private $capacity;
18+
19+
/**
20+
* Node constructor.
21+
*
22+
* @param int $capacity
23+
* @param \drupol\phptree\Node\NodeInterface|NULL $parent
24+
*/
25+
public function __construct(int $capacity = 0, NodeInterface $parent = null)
26+
{
27+
parent::__construct($parent);
28+
29+
if ($capacity < 0) {
30+
$capacity = 0;
31+
}
32+
33+
$this->capacity = $capacity;
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function capacity(): int
40+
{
41+
return $this->capacity;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
public function add(NodeInterface ...$nodes): NodeInterface
48+
{
49+
foreach ($nodes as $node) {
50+
$capacity = $this->capacity();
51+
52+
if (0 === $capacity || $this->degree() < $capacity) {
53+
parent::add($node);
54+
55+
continue;
56+
}
57+
58+
// @todo Find a way to get rid of this.
59+
$visitor = new BreadthFirstVisitor();
60+
61+
foreach ($visitor->traverse($this) as $node_visited) {
62+
if ($node_visited->degree() >= $capacity) {
63+
continue;
64+
}
65+
66+
$node_visited->add($node);
67+
68+
break;
69+
}
70+
}
71+
72+
return $this;
73+
}
74+
}

src/Node/NaryNodeInterface.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace drupol\phptree\Node;
6+
7+
/**
8+
* Class NaryNode
9+
*/
10+
interface NaryNodeInterface
11+
{
12+
/**
13+
* {@inheritdoc}
14+
*/
15+
public function capacity(): int;
16+
}

src/Node/NodeInterface.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function remove(NodeInterface ...$node): NodeInterface;
5353
/**
5454
* Get the children.
5555
*
56-
* @return NodeInterface[]
56+
* @return \drupol\phptree\Node\NodeInterface[]
5757
* The children.
5858
*/
5959
public function children(): array;

src/Node/ValueNode.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* Class ValueNode
99
*/
10-
class ValueNode extends Node implements ValueNodeInterface
10+
class ValueNode extends NaryNode implements ValueNodeInterface
1111
{
1212
/**
1313
* @var string|mixed|null
@@ -18,11 +18,12 @@ class ValueNode extends Node implements ValueNodeInterface
1818
* KeyValueNode constructor.
1919
*
2020
* @param mixed|null $value
21+
* @param int $capacity
2122
* @param \drupol\phptree\Node\NodeInterface|NULL $parent
2223
*/
23-
public function __construct($value = null, NodeInterface $parent = null)
24+
public function __construct($value = null, int $capacity = 0, NodeInterface $parent = null)
2425
{
25-
parent::__construct($parent);
26+
parent::__construct($capacity, $parent);
2627

2728
$this->value = $value;
2829
}

src/Visitor/AbstractVisitor.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\NodeInterface;

src/Visitor/BreadthFirstVisitor.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\NodeInterface;

src/Visitor/PostOrderVisitor.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\NodeInterface;

src/Visitor/PreOrderVisitor.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\NodeInterface;

src/Visitor/VisitorInterface.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
declare(strict_types = 1);
4+
35
namespace drupol\phptree\Visitor;
46

57
use drupol\phptree\Node\NodeInterface;

0 commit comments

Comments
 (0)