HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/deensekroon.komma-mediadesign.nl/wwwroot/App/Tree/Tree.php
<?php


namespace App\Tree;


include_once($_SERVER['DOCUMENT_ROOT'] . '/App/Tree/TreeNode.php');



class Tree
{
    /**
     * Tree of nodes
     * @var array
     */
    protected $nodes = [];

    /**
     * Index of nodes
     * @var array
     */
    protected $nodeIndex = [];

    /**
     * Array of ids with their level
     * @var array
     */
    protected $levelIndex = [];


    /**
     * Create the tree
     *
     * @param $nodes
     */
    public function make($nodes, $newNode = null)
    {
        // For node from request that is not save in the database yet
        if($newNode != null) $nodes = $this->replaceNewNodeInNodes($newNode,$nodes);

        // Explode nodes to separate levels
        list($l1,$l2,$l3) = $this->explodeLevels($nodes);

        // Create first level
        foreach($l1 as $node)
        {
            $this->nodes[$node->id] = $node;
        }

        // Create second level
        foreach($l2 as $node)
        {
            if(isset($this->nodes[$node->parent_id]))
                $this->nodes[$node->parent_id]->addChildNode($node);
        }
        // Create third level
        foreach($l3 as $node)
        {
            if( ! isset($this->nodes[$node->grandparent_id]) ) continue;
            $parentNode = $this->nodes[$node->grandparent_id]->childNodeById($node->parent_id);
            if( ! $parentNode) continue;
            $parentNode->addChildNode($node);
        }

        // Create first level
        foreach($l1 as $node)
        {
            $this->nodeIndex[$node->id] = $node;
        }

        // Create second level
        foreach($l2 as $node)
        {
            $this->nodeIndex[$node->id] = $node;
        }

        // Create third level
        foreach($l3 as $node)
        {
            $this->nodeIndex[$node->id] = $node;
        }

    }

    /**
     * Return tree nodes
     *
     * @return array
     */
    public function nodes()
    {
        return $this->nodes;
    }

    /**
     * Return tree node by id
     *
     * @return array
     */
    public function node($id)
    {
        if( ! isset($this->nodeIndex[$id])) return false;

        return $this->nodeIndex[$id];
    }



    /**
     * Explode nodes to separate levels
     *
     * @param $nodes
     * @return array
     */
    private function explodeLevels($nodes)
    {
        $level1 = [];
        $level2 = [];
        $level3 = [];

        foreach($nodes as $node)
        {
            $node = new TreeNode($node);

            // When no parent the level is 1
            if($node->parent_id == null)
            {
                $level1[] = $node;
                $this->levelIndex[$node->id] = 1;
                continue;
            }

            // When nog grandparent, the level is 2
            if($node->grandparent_id == null)
            {
                $level2[] = $node;
                $this->levelIndex[$node->id] = 2;
                continue;
            }

            // The level must be 3
            $level3[] = $node;
            $this->levelIndex[$node->id] = 3;
        }

        return [$level1,$level2,$level3];
    }


    /**
     * This is used when a category isn't saved yet,
     * but we need a tree with new request values
     *
     * @param $newNode
     * @param $nodes
     * @return array
     */
    private function replaceNewNodeInNodes($newNode, $nodes)
    {
        if($newNode->parent_id == 'null') $newNode->parent_id = null;

        // New node has no grandparent_id yet
        $parentKey = $this->findKeyForObjectIdInArray($nodes,$newNode->parent_id);
        if($parentKey !== false)
        {
            $parentNode = $nodes[$parentKey];
            $newNode->parent_title_nl = $parentNode->title_nl;
            $newNode->parent_title_en = $parentNode->title_en;

            $newNode->grandparent_id = $parentNode->parent_id;
            $newNode->grandparent_title_nl = $parentNode->parent_title_nl;
            $newNode->grandparent_title_en = $parentNode->parent_title_en;
        }

        if($key = $this->findKeyForObjectIdInArray($nodes,$newNode->id) !== false)
        {
            // New Node already exists
            // So replace it in the array of nodes
            $nodes[$key] = $newNode;
        }
        else
        {
            $nodes[] = $newNode;
        }

        return $nodes;
    }

    /**
     * @param $array
     * @param $id
     * @return bool
     */
    private function findKeyForObjectIdInArray($array, $id)
    {
        $id = (int) $id;

        foreach($array as $key => $node)
        {
            if ($id == $node->id) return $key;
        }
        return false;
    }
}