Passed
Push — master ( d5f140...355cc7 )
by Pol
02:12
created

NikicPhpParserImporter::createNewNode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

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