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


root
electronic
tv
player
dvd
mp3
camera
appliance
refrigerator
hoover
washer
computer
desktop
notebook
apple
others
tablet
printer
reference
about
delivery
payment