1<?php
2
3namespace ComboStrap;
4
5class PathTreeNode extends TreeNode
6{
7
8
9    const CANONICAL = "path-tree";
10
11    private Path $path;
12
13    public function __construct(?Path $path)
14    {
15        $this->path = $path;
16    }
17
18    /**
19     * Build the tree from the file systems with the {@link FileSystems::getChildren()}
20     * function
21     */
22    public static function buildTreeViaFileSystemChildren(Path $rootSpace = null): PathTreeNode
23    {
24        $root = PathTreeNode::createPathTreeNodeFromPath($rootSpace);
25        self::buildTreeFromFileSystemRecursively($root);
26        return $root;
27    }
28
29    /**
30     * Build the tree from the file systems with the {@link FileSystems::getChildren()}
31     * function
32     *
33     * @param PathTreeNode $parentPathTreeNode
34     * @return void
35     */
36    public static function buildTreeFromFileSystemRecursively(PathTreeNode $parentPathTreeNode)
37    {
38        $parentPath = $parentPathTreeNode->getPath();
39        $childrenPath = FileSystems::getChildren($parentPath);
40        foreach ($childrenPath as $childPath) {
41            $childTreeNode = PathTreeNode::createPathTreeNodeFromPath($childPath);
42            try {
43                $parentPathTreeNode->appendChild($childTreeNode);
44            } catch (ExceptionBadState $e) {
45                throw new ExceptionRuntimeInternal("We shouldn't add the node two times. ", self::CANONICAL, 1, $e);
46            }
47            if (FileSystems::isDirectory($childPath)) {
48                self::buildTreeFromFileSystemRecursively($childTreeNode);
49            }
50        }
51    }
52
53
54    private static function createPathTreeNodeFromPath(Path $path): PathTreeNode
55    {
56        return new PathTreeNode($path);
57    }
58
59    /**
60     * Build the tree from a array of ids. The build is done via the {@link Path::getParent()}
61     * @param array $ids
62     * @return TreeNode
63     */
64    public static function buildTreeViaParentPath(array $ids): TreeNode
65    {
66
67        $rootNode = null;
68        /**
69         * @var PathTreeNode[]
70         */
71        $nodeByIds = [];
72        foreach ($ids as $id) {
73            $path = WikiPath::createMarkupPathFromId($id);
74            $actualNode = $nodeByIds[$path->getWikiId()] ?? null;
75            if ($actualNode === null) {
76                $actualNode = PathTreeNode::createPathTreeNodeFromPath($path);
77                $nodeByIds[$path->getWikiId()] = $actualNode;
78            }
79            while (true) {
80                try {
81                    /**
82                     * @var WikiPath $parentPath
83                     */
84                    $parentPath = $actualNode->getPath()->getParent();
85                    $parentPathNode = $nodeByIds[$parentPath->getWikiId()] ?? null;
86                    if ($parentPathNode === null) {
87                        $parentPathNode = PathTreeNode::createPathTreeNodeFromPath($parentPath);
88                        $nodeByIds[$parentPath->getWikiId()] = $parentPathNode;
89                    }
90                    $parentPathNode->appendChild($actualNode);
91
92                    // Loop
93                    $actualNode = $parentPathNode;
94                } catch (ExceptionNotFound $e) {
95                    break;
96                }
97            }
98            if ($rootNode === null) {
99                $rootNode = $actualNode;
100            }
101
102        }
103        return $rootNode;
104    }
105
106    public function getPath(): Path
107    {
108        return $this->path;
109    }
110
111    function getTreeIdentifier(): string
112    {
113        return $this->path->toAbsoluteId();
114    }
115
116
117}
118