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