fork download
  1. <?php
  2.  
  3. class Node {
  4.  
  5. private $parentNode = NULL;
  6. private $child = array();
  7. protected $name;
  8.  
  9. public function __construct($name) {
  10. $this->name = $name;
  11. }
  12. public function __toString() {
  13. $node = "\nNameNode: " . $this->name . "\n";
  14. /* $node .= "ParentName: " . $this->parentNode->getName() . "\n";
  15.   foreach ($this->child as $child) {
  16.   $node .= "ChildName: " . $child->getName() ."\n";
  17.   }
  18.   */
  19. return $node;
  20. }
  21. public function getName() {
  22. return $this->name;
  23. }
  24.  
  25. public function getParentNode(){
  26. if (isset($this->parentNode)) {
  27. return $this->parentNode;
  28. }
  29. return NULL;
  30. }
  31. public function getChildrenNode() {
  32. return $this->child;
  33. }
  34.  
  35. public function getAllParents(){
  36. if (NULL == $this->getParentNode()) {
  37. return array();
  38. } else {
  39. $parent = $this->getParentNode();
  40. $parents = $parent->getAllParents();
  41. $parents[] = $parent;
  42. return $parents;
  43. }
  44. }
  45. public function getAllChildren(){
  46. $childrenNode = $this->getChildrenNode();
  47. $children = $childrenNode;
  48. foreach ($childrenNode as $child) {
  49. $children = array_merge($children, $child->getAllChildren());
  50. }
  51.  
  52. return $children;
  53. }
  54.  
  55. public function getDepth() {
  56. $children = $this->child;
  57. $depth = -1;
  58. //echo $this->name() . '->';
  59. foreach ($children as $child) {
  60. $depth = max($depth, $child->getDepth());
  61. }
  62. $depth++;
  63. return $depth;
  64. }
  65.  
  66. public function getDescendantsCount(){
  67. $DescendantsCount = 0;
  68. $children = $this->child;
  69. echo $this->getName() . '->';
  70. foreach ($children as $child) {
  71. $DescendantsCount++;
  72. $DescendantsCount += $child->getDescendantsCount();
  73. }
  74. return $DescendantsCount;
  75. }
  76.  
  77. public function appendChild(Node $child) {
  78.  
  79. if ($this == $child) {
  80. throw new Exception("ОШИБКА! Нельзя делать обьект " . $this->getName() . " родителем самого себя.\n");
  81. }
  82.  
  83. $parents = $this->getAllParents();
  84. if (in_array($child, $parents)) {
  85. throw new Exception("ОШИБКА! Нельзя делать обьект " . $this->getName() . " потомком самого себя.\n");
  86. }
  87.  
  88. $child->remove();
  89.  
  90. $this->child[] = $child;
  91. $child->parentNode = $this;
  92. }
  93.  
  94. public function remove(){
  95. if (isset($this->parentNode)) {
  96. echo "\nУдаление\n";
  97. $parentNode = $this->parentNode;
  98.  
  99. $children = $parentNode->child;
  100. $key = array_search($this , $children);
  101. unset($parentNode->child[$key]);
  102.  
  103. $this->parentNode = null;
  104. }
  105. }
  106.  
  107. public function getNextSibling(){
  108. $parentNode = $this->parentNode;
  109. if (NULL ==$parentNode) {
  110. return NULL;
  111. }
  112. $siblings = $parentNode->getChildrenNode();
  113.  
  114. while (current($siblings) <> $this) {
  115. next($siblings);
  116. }
  117.  
  118. return next($siblings);
  119. }
  120. public function getPreviousSibling(){
  121. $parentNode = $this->parentNode;
  122. if (NULL ==$parentNode) {
  123. return NULL;
  124. }
  125. $siblings = $parentNode->getChildrenNode();
  126.  
  127. //Переходим к элементу для которого требуется найти брата
  128. while (current($siblings) <> $this) {
  129. next($siblings);
  130. }
  131.  
  132. return prev($siblings);
  133.  
  134. }
  135.  
  136.  
  137. public function walk($function) {
  138. $allChildren = $this->getAllChildren();
  139. $return = array();
  140. $callback =
  141. function ( $child ) use ( $function, &$return) {
  142. $return[] = "Имя узла: " . $child->getName() . " Количество потомков: "
  143. . $child->$function();
  144. };
  145. array_walk( $allChildren, $callback );
  146. print_r($return);
  147. }
  148. // обходит всех потомков $node, для каждого вызывая функцию
  149.  
  150.  
  151.  
  152. }
  153.  
  154. class Creator {
  155. function createTree() {
  156. $root = new Node('root');
  157. $electronic = new Node('electronic');
  158. $root->appendChild($electronic);
  159. $tv = new Node('tv');
  160. $electronic->appendChild($tv);
  161. $player = new Node('player');
  162. $electronic->appendChild($player);
  163. $dvd = new Node('dvd');
  164. $player->appendChild($dvd);
  165. $mp3 = new Node('mp3');
  166. $player->appendChild($mp3);
  167.  
  168. $camera = new Node('camera');
  169. $electronic->appendChild($camera);
  170.  
  171. $appliance = new Node('appliance');
  172. $root->appendChild($appliance);
  173. $refrigerator = new Node('refrigerator');
  174. $appliance->appendChild($refrigerator);
  175. $hoover = new Node('hoover');
  176. $appliance->appendChild($hoover);
  177. $washer = new Node('washer');
  178. $appliance->appendChild($washer);
  179.  
  180. $computer = new Node('computer');
  181. $root->appendChild($computer);
  182. $desktop = new Node('desktop');
  183. $computer->appendChild($desktop);
  184. $notebook = new Node('notebook');
  185. $computer->appendChild($notebook);
  186. $apple = new Node('apple');
  187. $notebook->appendChild($apple);
  188. $others = new Node('others');
  189. $notebook->appendChild($others);
  190.  
  191. $tablet = new Node('tablet');
  192. $computer->appendChild($tablet);
  193. $printer = new Node('printer');
  194. $computer->appendChild($printer);
  195.  
  196. $reference = new Node('reference');
  197. $root->appendChild($reference);
  198. $about = new Node('about');
  199. $reference->appendChild($about);
  200. $delivery = new Node('delivery');
  201. $reference->appendChild($delivery);
  202. $payment = new Node('payment');
  203. $reference->appendChild($payment);
  204. return $root;
  205. }
  206. }
  207.  
  208. class View {
  209.  
  210. function getColumn($node, $width) {
  211. $level = count($node->getAllParents());
  212.  
  213. if ($level == 1) {
  214. $word = " " . $node->getName();
  215. $column[] = str_pad($word, $width);
  216. $column[] = str_pad('', $width);
  217. }
  218. if ($level == 2) {
  219. $word = " -" . $node->getName();
  220. $column[] = str_pad($word, $width);
  221. }
  222. if ($level > 2) {
  223. $indent = ($level-1) * 2;
  224. $word = str_pad(' ', $indent ) . $node->getName();
  225. $column[] = str_pad($word, $width);
  226. }
  227.  
  228. $children = $node->getChildrenNode();
  229. foreach ($children as $child) {
  230. $getColumn = $this->getColumn($child, $width);
  231. $column = array_merge($column,$getColumn);
  232. }
  233.  
  234. return $column;
  235.  
  236. }
  237.  
  238. function getWidthColumn($root) {
  239. //определение ширины колонки
  240. $rootChildren = $root->getChildrenNode();
  241. $widthColumn = array();
  242.  
  243. foreach ($rootChildren as $rootChild) {
  244. //ширина первого пункта меню
  245. $width = mb_strlen($rootChild->getName()) + 2 ;
  246. $allChildrenNode = $rootChild->getAllChildren();
  247.  
  248. foreach ($allChildrenNode as $node) {
  249. $level = count($node->getAllParents());
  250.  
  251. $thisWidthNode = mb_strlen($node->getName()) + (2 * ($level - 1));
  252. $width = max($width,$thisWidthNode);
  253. }
  254. //к ширине строки прибавляется расстояние между колонками 4
  255. $widthColumn[] = $width+4;
  256. }
  257. return $widthColumn;
  258. }
  259.  
  260. function getHeightColumn($root){
  261. $heightColumn = 0;
  262. $rootChildren = $root->getChildrenNode();
  263.  
  264.  
  265. foreach ($rootChildren as $rootChild) {
  266.  
  267. //находим пункты меню(кроме первых уровней) данного столбца.
  268. $menuItems = $rootChild->getAllChildren();
  269. //получаем колличество строк в меню
  270. $heightThisColumn = count($menuItems) + 2;
  271. $heightColumn = max($heightColumn, $heightThisColumn);
  272. }
  273.  
  274. return $heightColumn;
  275. }
  276.  
  277. function getTextMenu($root) {
  278. $widthColumn = $this->getWidthColumn($root);
  279. $heightColumn = $this->getHeightColumn($root);
  280.  
  281.  
  282. $children = $root->getChildrenNode();
  283. $countColumn = count($children);
  284. $menu = '';
  285.  
  286. $column = array();
  287. $i = -1;
  288. foreach ($children as $child) {
  289. $i++;
  290. $columns[] = $this->getColumn($child, $widthColumn[$i]);
  291. }
  292.  
  293. for ( $i = 0 ; $i < $heightColumn ; $i++ ) {
  294. for ( $j = 0 ; $j < $countColumn ; $j++ ) {
  295. if (isset($columns[$j][$i])) {
  296. $menu.= $columns[$j][$i];
  297. }else{
  298. $menu.= str_pad('', $widthColumn[$j]);
  299. }
  300. }
  301. $menu .= "\n";
  302. }
  303.  
  304. return $menu;
  305. }
  306.  
  307. function writeMenu(){
  308. $creator = new Creator();
  309. $root = $creator->createTree();
  310. $menu = $this->getTextMenu($root);
  311. return $menu;
  312. }
  313. }
  314.  
  315. $view = new View;
  316. echo $view->writeMenu();
  317.  
  318.  
  319.  
  320.  
Success #stdin #stdout 0.01s 20520KB
stdin
Standard input is empty
stdout
  electronic      appliance         computer      reference    
                                                               
 -tv             -refrigerator     -desktop      -about        
 -player         -hoover           -notebook     -delivery     
    dvd          -washer              apple      -payment      
    mp3                               others                   
 -camera                           -tablet                     
                                   -printer