TreeFactory   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 59.51%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 4
dl 0
loc 119
ccs 25
cts 42
cp 0.5951
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A strict() 0 6 1
D create() 0 44 9
A addAsChild() 0 11 3
A addAsRoot() 0 6 2
A addOrphan() 0 7 2
1
<?php
2
3
namespace Vine;
4
5
use Vine\Transposable;
6
7
class TreeFactory
8
{
9
    /**
10
     * Create tree in strict mode.
11
     * This will throw exception if index contains invalid references.
12
     * e.g. parent reference to non-existing node
13
     *
14
     * @var bool
15
     */
16
    private $strict = false;
17
18
    private $index;
19
    private $orphans;
20
    private $roots;
21
22 18
    public function __construct()
23
    {
24 18
        $this->index = new NodeCollection();
25 18
        $this->roots = new NodeCollection();
26 18
        $this->orphans = [];
27 18
    }
28
29
    /**
30
     * @param bool $strict
31
     * @return $this
32
     */
33
    public function strict($strict = true)
34
    {
35
        $this->strict = !!$strict;
36
37
        return $this;
38
    }
39
40 18
    public function create(Transposable $transposable)
41
    {
42 18
        foreach($transposable->all() as $i => $entry)
43
        {
44 18
            $id = is_object($entry) ? $entry->{$transposable->key()}: $entry[$transposable->key()];
45 18
            $parentId = is_object($entry) ? $entry->{$transposable->parentKey()}: $entry[$transposable->parentKey()];
46
47 18
            $entryNode = new Node($entry);
48
49 18
            $this->index[$id] = $entryNode;
50 18
            $this->addAsChild($parentId, $entryNode);
51 18
            $this->addAsRoot($parentId, $entryNode);
52
        }
53
54
        // All orphans need to be assigned to their respective parents
55 18
        foreach($this->orphans as $parentId => $orphans)
56
        {
57
            if(!isset($this->index[$parentId]))
58
            {
59
                // Strict check which means there is a node assigned to an non-existing parent
60
                if($this->strict)
61
                {
62
                    throw new \LogicException('Parent reference to a non-existing node via identifier ['.$parentId.']');
63
                }
64
65
                continue;
66
            }
67
68
            $this->index[$parentId]->addChildren($orphans->all());
69
        }
70
71
        // At this point we allow to alter each entry.
72
        // Useful to add values depending on the node structure
73 18
        if(method_exists($transposable,'entry'))
74
        {
75
            foreach($this->index as $node)
76
            {
77
                $node->replaceEntry($transposable->entry($node));
0 ignored issues
show
Bug introduced by
The method entry() does not seem to exist on object<Vine\Transposable>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
78
            }
79
        }
80
81
        // Collect all root nodes because they contain the entire tree
82 18
        return new Tree($this->roots, $this->index);
83
    }
84
85
    /**
86
     * @param $parentId
87
     * @param $entryNode
88
     * @return mixed
89
     */
90 18
    private function addAsChild($parentId, $entryNode)
91
    {
92 18
        if (!$parentId) return;
93
94 18
        if (isset($this->index[$parentId])) {
95 18
            $this->index[$parentId]->addChildren([$entryNode]);
96 18
            return;
97
        }
98
99
        $this->addOrphan($parentId, $entryNode);
100
    }
101
102
    /**
103
     * @param $parentId
104
     * @param $entryNode
105
     * @return mixed
106
     */
107 18
    private function addAsRoot($parentId, $entryNode)
108
    {
109 18
        if ($parentId) return;
110
111 18
        $this->roots[] = $entryNode;
112 18
    }
113
114
    /**
115
     * @param $parentId
116
     * @param $entryNode
117
     */
118
    private function addOrphan($parentId, $entryNode)
119
    {
120
        if (!isset($this->orphans[$parentId])) {
121
            $this->orphans[$parentId] = new NodeCollection();
122
        }
123
        $this->orphans[$parentId][] = $entryNode;
124
    }
125
}
126