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;
}
}