open-orchestra/open-orchestra-display-bundle

View on GitHub
DisplayBundle/Manager/TreeManager.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace OpenOrchestra\DisplayBundle\Manager;

use OpenOrchestra\ModelInterface\Model\ReadNodeInterface;

/**
 * Class TreeManager
 */
class TreeManager
{
    /**
     * @param array $nodes
     *
     * @return array
     */
    public function generateTree($nodes)
    {
        $superRoot = count(array_filter($nodes, function (ReadNodeInterface $node) {
            return '-' == $node->getParentId();
        }))? '-': 'root';

        $list = array();
        $list[$superRoot] = array();
        foreach ($nodes as $node) {
            if ($superRoot !== $node->getParentId() && $this->parentInList($node->getParentId(), $nodes)) {
                $list[$node->getParentId()][] = $node;
                continue;
            }
            $list[$superRoot][] = $node;
        }

        $tree = $this->createTree($list[$superRoot], $list);

        return $tree;
    }

    /**
     * @param array|ReadNodeInterface $nodes
     * @param array                   $list
     *
     * @return array
     */
    protected function createTree($nodes, $list)
    {
        $tree = array();

        if (is_array($nodes)) {
            foreach ($nodes as $node) {
                $position = $this->getNodePosition($node, $tree);
                $tree[$position] = array('node' => $node, 'child' => $this->getChildren($node, $list));
            }
            $tree = $this->sortArray($tree);
        } elseif (!empty($nodes)) {
            $tree = array('node' => $nodes, 'child' => $this->getChildren($nodes, $list));
        }

        return $tree;
    }

    /**
     * @param ReadNodeInterface $node
     * @param array             $list
     *
     * @return array
     */
    protected function getChildren(ReadNodeInterface $node, $list)
    {
        $children = array();

        if (!empty($list[$node->getNodeId()]) && is_array($list[$node->getNodeId()])) {
            foreach ($list[$node->getNodeId()] as $child) {
                $position = $this->getNodePosition($child, $children);
                $children[$position] = $this->createTree($child, $list);
            }
        }

        $children = $this->sortArray($children);

        return $children;
    }

    /**
     * @param string $parentId
     * @param array  $list
     *
     * @return bool
     */
    protected function parentInList($parentId, $list)
    {
        foreach ($list as $node) {
            if ($parentId === $node->getNodeId()) {
                return true;
            }
        }

        return false;
    }

    /**
     * @param ReadNodeInterface $node
     * @param array             $tree
     *
     * @return mixed
     */
    protected function getNodePosition(ReadNodeInterface $node, $tree)
    {
        $position = $node->getOrder();
        while (array_key_exists($position, $tree)) {
            $position++;
        }

        return $position;
    }

    /**
     * @param array $tree
     *
     * @return mixed
     */
    protected function sortArray($tree)
    {
        if (!empty($tree)) {
            ksort($tree);
        }

        return $tree;
    }
}