<?php
class Node {
private $parentNode = NULL;
private $child = array(); protected $name;
public function __construct($name) {
$this->name = $name;
}
public function __toString() {
$node = "\nNameNode: " . $this->name . "\n";
/* $node .= "ParentName: " . $this->parentNode->getName() . "\n";
foreach ($this->child as $child) {
$node .= "ChildName: " . $child->getName() ."\n";
}
*/
return $node;
}
public function getName() {
return $this->name;
}
public function getParentNode(){
return $this->parentNode ? $this->parentNode : NULL;
}
public function getChildrenNode() {
return $this->child;
}
public function getAllParents(){
if (!$this->getParentNode()) {
} else {
$parent = $this->getParentNode();
$parents = $parent->getAllParents();
$parents[] = $parent;
return $parents;
}
}
public function getAllChildren(){
$childrenNode = $this->getChildrenNode();
$children = $childrenNode;
foreach ($childrenNode as $child) {
$children = array_merge($children, $child->getAllChildren()); }
return $children;
}
public function getDepth() {
$children = $this->child;
$depth = -1;
//echo $this->name() . '->';
foreach ($children as $child) {
$depth = max($depth, $child->getDepth()); }
$depth++;
return $depth;
}
public function getDescendantsCount(){
$DescendantsCount = 0;
$children = $this->child;
echo $this->getName() . '->';
foreach ($children as $child) {
$DescendantsCount++;
$DescendantsCount += $child->getDescendantsCount();
}
return $DescendantsCount;
}
public function appendChild(Node $child) {
if ($this == $child) {
throw new Exception("ОШИБКА! Нельзя делать обьект " . $this->getName() . " родителем самого себя.\n");
}
$parents = $this->getAllParents();
throw new Exception("ОШИБКА! Нельзя делать обьект " . $this->getName() . " потомком самого себя.\n");
}
$child->remove();
$this->child[] = $child;
$child->parentNode = $this;
}
public function remove(){
if ($this->parentNode) {
echo "\nУдаление\n";
$parentNode = $this->parentNode;
$children = $parentNode->child;
unset($parentNode->child[$key]);
$this->parentNode = null;
}
}
public function getNextSibling(){
$parentNode = $this->parentNode;
if (NULL ==$parentNode) {
return NULL;
}
$siblings = $parentNode->getChildrenNode();
while (current($siblings) <> $this) { }
}
public function getPreviousSibling(){
$parentNode = $this->parentNode;
if (NULL ==$parentNode) {
return NULL;
}
$siblings = $parentNode->getChildrenNode();
//Переходим к элементу для которого требуется найти брата
while (current($siblings) <> $this) { }
}
public function walk($function) {
$children = $this->getChildrenNode();
foreach ($children as $child) {
$child->walk($function);
}
}
}
class Creator {
function createTree() {
(
(
(
(
),
),
(
'refrigerator' => array(), ),
(
(
),
),
(
)
)
);
function getObjectTree($arrayTree, $parent)
{
//рекурсивная свистопляска
foreach ($arrayTree as $name => $node)
{
$$name = new Node($name);
if ($parent) { $parent->appendChild($$name); }
getObjectTree($node, $$name);
}
//если узел лишён родителя, то его нужно вывести
if (!$parent) {return $$name;}
}
$parent = NULL;
$root = getObjectTree($arrayTree, $parent);
return $root;
}
}
class View {
const COLUMN_SPACING = 4;
function getColumn($node, $width) {
$level = count($node->getAllParents());
if ($level == 1) {
$word = " " . $node->getName();
$column[] = str_pad($word, $width); }
if ($level == 2) {
$word = " -" . $node->getName();
$column[] = str_pad($word, $width); }
if ($level > 2) {
$indent = ($level-1) * 2;
$word = str_pad(' ', $indent ) . $node->getName(); $column[] = str_pad($word, $width); }
$children = $node->getChildrenNode();
foreach ($children as $child) {
$getColumn = $this->getColumn($child, $width);
}
return $column;
}
function getWidthColumn($root) {
//определение ширины колонки
$rootChildren = $root->getChildrenNode();
foreach ($rootChildren as $rootChild) {
//ширина первого пункта меню
$width = mb_strlen($rootChild->getName()) + 2 ; $allChildrenNode = $rootChild->getAllChildren();
foreach ($allChildrenNode as $node) {
$level = count($node->getAllParents());
$thisWidthNode = mb_strlen($node->getName()) + (2 * ($level - 1)); $width = max($width,$thisWidthNode); }
//к ширине строки прибавляется расстояние между колонками 4
$widthColumn[] = $width+self::COLUMN_SPACING;
}
return $widthColumn;
}
function getHeightColumn($root){
$heightColumn = 0;
$rootChildren = $root->getChildrenNode();
foreach ($rootChildren as $rootChild) {
//находим пункты меню(кроме первых уровней) данного столбца.
$menuItems = $rootChild->getAllChildren();
//получаем колличество строк в меню
$heightThisColumn = count($menuItems) + 2; $heightColumn = max($heightColumn, $heightThisColumn); }
return $heightColumn;
}
function getTextMenu($root) {
$widthColumn = $this->getWidthColumn($root);
$heightColumn = $this->getHeightColumn($root);
$children = $root->getChildrenNode();
$countColumn = count($children); $menu = '';
$i = -1;
foreach ($children as $child) {
$i++;
$columns[] = $this->getColumn($child, $widthColumn[$i]);
}
for ( $i = 0 ; $i < $heightColumn ; $i++ ) {
for ( $j = 0 ; $j < $countColumn ; $j++ ) {
if (isset($columns[$j][$i])) { $menu.= $columns[$j][$i];
}else{
$menu.= str_pad('', $widthColumn[$j]); }
}
$menu .= "\n";
}
return $menu;
}
function writeMenu(){
$creator = new Creator();
$root = $creator->createTree();
$menu = $this->getTextMenu($root);
return $menu;
}
}
//$view = new View;
//echo $view->writeMenu() . "\n";
//тут тестирую функцию walk
echo "приступить к тесту \n\n\n";
function myFunction($node) {
echo $node->getName() . "\n";
}
$creator = new Creator;
$root = $creator->createTree();
$root->walk('myFunction');