Passed
Push — master ( 835266...50b7f4 )
by Pol
02:47
created

NikicPhpParser::getAllNodeChildren()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 1
nop 1
dl 0
loc 20
ccs 11
cts 11
cp 1
crap 2
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace loophp\phptree\Importer;
6
7
use Exception;
8
use loophp\phptree\Node\AttributeNode;
9
use loophp\phptree\Node\AttributeNodeInterface;
10
use loophp\phptree\Node\NodeInterface;
11
use PhpParser\Node;
12
use SplObjectStorage;
13
14
use function is_array;
15
16
/**
17
 * Class NikicPhpParser.
18
 */
19
final class NikicPhpParser implements ImporterInterface
20
{
21
    /**
22
     * @var SplObjectStorage
23
     */
24
    private $nodeMap;
25
26 2
    public function __construct()
27
    {
28 2
        $this->nodeMap = new SplObjectStorage();
29 2
    }
30
31
    /**
32
     * @param Node[] $data
33
     *
34
     * @throws Exception
35
     *
36
     * @return \loophp\phptree\Node\NodeInterface
37
     */
38 1
    public function import($data): NodeInterface
39
    {
40 1
        return (new AttributeNode(['label' => 'root']))
41 1
            ->add(...$this->parseNodes(...$data));
42
    }
43
44
    /**
45
     * @param \PhpParser\Node $astNode
46
     *
47
     * @throws \Exception
48
     *
49
     * @return \loophp\phptree\Node\NodeInterface
50
     */
51 1
    private function createNewNode(Node $astNode): NodeInterface
52
    {
53
        $defaultAttributes = [
54 1
            'label' => $astNode->getType(),
55 1
            'astNode' => $astNode,
56
        ];
57
58 1
        return (new AttributeNode($defaultAttributes))
59 1
            ->add(...$this->parseNodes(...$this->getAllNodeChildren($astNode)));
60
    }
61
62
    /**
63
     * @param \PhpParser\Node $astNode
64
     *
65
     * @return array<int, Node>
66
     */
67 1
    private function getAllNodeChildren(Node $astNode): array
68
    {
69
        /** @var array<int, array<int, Node>> $astNodes */
70 1
        $astNodes = array_map(
71
            static function (string $subNodeName) use ($astNode): array {
72 1
                $subNodes = $astNode->{$subNodeName};
73
74 1
                if (!is_array($subNodes)) {
75 1
                    $subNodes = [$subNodes];
76
                }
77
78 1
                return array_filter(
79 1
                    $subNodes,
80 1
                    'is_object'
81
                );
82 1
            },
83 1
            $astNode->getSubNodeNames()
84
        );
85
86 1
        return array_merge(...$astNodes);
87
    }
88
89
    /**
90
     * @param \PhpParser\Node $astNode
91
     * @param callable $default
92
     *
93
     * @return \loophp\phptree\Node\AttributeNodeInterface
94
     */
95 1
    private function getNodeFromCache(Node $astNode, callable $default): AttributeNodeInterface
96
    {
97 1
        if (false === $this->nodeMap->contains($astNode)) {
98 1
            $this->nodeMap->attach($astNode, $default($astNode));
99
        }
100
101 1
        return $this->nodeMap->offsetGet($astNode);
102
    }
103
104
    /**
105
     * @param Node ...$astNodes
106
     *
107
     * @throws \Exception
108
     *
109
     * @return AttributeNodeInterface[]
110
     */
111 1
    private function parseNodes(Node ...$astNodes): array
112
    {
113 1
        $treeNodes = [];
114
115 1
        foreach ($astNodes as $astNode) {
116 1
            $treeNodes[] = $this->getNodeFromCache($astNode, [$this, 'createNewNode']);
117
        }
118
119 1
        return $treeNodes;
120
    }
121
}
122