<?php
class TreeElement
{
protected $nodeName;
protected $childNodes=[];
protected $parentNode;
public function __construct($nodeName){
$this->nodeName = $nodeName;
}
public function getNodeName(){
return $this->nodeName;
}
public function findDescendant($name){
foreach($this->childNodes as $child){
if($child->getNodeName()==$name){
return $child;
}
else{
$desc = $child->findDescendant($name);
if($desc && $desc->getNodeName()==$name){
return $desc;
}
}
}
return null;
}
public function countChildNodes(){
return count($this->childNodes); }
public function countDescendants(){
$descCount = 0;
foreach ($this->childNodes as $child) {
$descCount++;
$descCount+= $child->countDescendants();
}
return $descCount;
}
public function addChild(TreeElement $child){
if($this->getRootElement()->findDescendant($child->getNodeName())){
return false;
}
$this->childNodes[] = $child;
$child->setParentNode($this);
}
public function removeChild($node){
foreach ($this->childNodes as $key => $child) {
if($child === $node){
unset($this->childNodes[$key]); }
}
}
public function isRoot(){
if(!$this->parentNode){
return true;
}
return false;
}
public function getRootElement(){
$currentNode = $this;
while (!$currentNode->isRoot()){
$currentNode = $currentNode->parentNode;
};
return $currentNode;
}
public function getDepth(){
$depth = 0;
if($this->parentNode){
$depth++;
$depth+= $this->parentNode->getDepth();
}
return $depth;
}
public function getChildNodes(){
return $this->childNodes;
}
public function setChildNodes($newNodes){
$this->childNodes = [];
foreach ($newNodes as $child) {
$this->addChild($child);
}
}
public function getParentNode(){
return $this->parentNode;
}
public function setParentNode($node){
$this->parentNode = $node;
}
public function isDescendant($node){
if($node->isAncestor($this)){
return true;
}
return false;
}
public function isAncestor($node){
foreach ($this->childNodes as $child) {
if($node===$child){
return true;
}
elseif($child->isAncestor($node)){
return true;
}
}
return false;
}
public function getNextSibling(){
$parent = $this->parentNode;
if(!$parent){
return false;
}
$previous = NULL;
foreach ($parent->getChildNodes() as $child) {
if($previous==$this){
return $child;
}
$previous = $child;
}
return false;
}
public function getPreviousSibling(){
$parent = $this->parentNode;
$previous = NULL;
if(!$parent){
return false;
}
foreach ($parent->getChildNodes() as $child) {
if($this == $child){
return $previous;
}
$previous = $child;
}
return false;
}
public function moveSibling($n){
$parent = $this->parentNode;
if(!$parent){
return false;
}
$children = $parent->getChildNodes();
foreach ($children as $key => $child) {
if($child===$this){
break;
}
}
$parent->setChildNodes($children);
}
public function moveNode($parent){
if(!$this->parentNode){
return false;
}
$this->parentNode->removeChild($this);
$parent->addChild($this);
}
public function displayAsCatalog(){
$children = "";
$depth = "";
if($this->countDescendants()>0){
$children = " (".$this->countDescendants().") ";
}
for($i = 0; $i<$this->getDepth();$i++){
$depth.="...";
}
echo $depth.$this->nodeName.$children."\n";
foreach ($this->childNodes as $child) {
$child->displayAsCatalog();
}
}
}
$tech = new TreeElement("Бытовая техника");
$tech->addChild(new TreeElement('Телевизоры'));
$televisors = $tech->findDescendant('Телевизоры');
$televisors->addChild(new TreeElement('LCD-телевизоры'));
$televisors->addChild(new TreeElement('Плазменные'));
$tech->addChild(new TreeElement('Холодильники'));
$refrigirators = $tech->findDescendant('Холодильники');
$refrigirators->addChild(new TreeElement('Маленькие'));
$refrigirators->addChild(new TreeElement('Средние'));
$refrigirators->addChild(new TreeElement('Большие'));
$tech->displayAsCatalog();