/** * Creates a NamedNode tree from an array with path => nodeValue entries. * @param array $tree The collapsed tree: [ $path => $data, ... ] * @return \arc\tree\NamedNode an object tree with parent/children relations */ public static function expand($tree = null) { if (is_object($tree) && isset($tree->childNodes)) { return $tree; //FIXME: should we clone the tree to avoid shared state? } $root = new \arc\tree\NamedNode(); if (!is_array($tree)) { return $root; // empty tree } $previousParent = $root; foreach ($tree as $path => $data) { $previousPath = $previousParent->getPath(); $subPath = \arc\path::diff($previousPath, $path); if ($subPath) { // create missing parent nodes, input tree may be sparsely filled $node = \arc\path::reduce($subPath, function ($previous, $name) { if ($name == '..') { return $previous->parentNode; } return $previous->appendChild($name); }, $previousParent); } else { // means the previousParent is equal to the current path, e.g. the root $node = $previousParent; } $node->nodeValue = $data; $previousParent = $node; } return $root; }
function testDiff() { $this->assertTrue(\arc\path::diff('/a/', '/a/b/') == 'b/'); $this->assertTrue(\arc\path::diff('/a/', '/b/') == '../b/'); }