fork(2) 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. $allChildren = $this->getAllChildren();
  136. //к потомкам добавляем их родетеля
  137. $allChildren = array_merge(array($this), $allChildren);
  138.  
  139. //используем на каждом элементе пользовательскую функцию
  140. foreach ($allChildren as $children) {
  141. call_user_func($function, $children);
  142. }
  143. //Работает только на первом элементе(>_<) >>> call_user_func_array($function, $allChildren);
  144.  
  145. }
  146.  
  147. }
  148.  
  149. class Creator {
  150.  
  151. function createTree() {
  152. $arrayTree = array
  153. (
  154. 'root' => array
  155. (
  156. 'electronic' => array
  157. (
  158. 'tv' => array(),
  159. 'player' => array
  160. (
  161. 'dvd' => array(),
  162. 'mp3' => array()
  163. ),
  164. 'camera' => array()
  165. ),
  166. 'appliance' => array
  167. (
  168. 'refrigerator' => array(),
  169. 'hoover' => array(),
  170. 'washer' => array()
  171. ),
  172. 'computer' => array
  173. (
  174. 'desktop' => array(),
  175. 'notebook' => array
  176. (
  177. 'apple' => array(),
  178. 'others' => array()
  179. ),
  180. 'tablet' => array(),
  181. 'printer' => array()
  182. ),
  183. 'reference' => array
  184. (
  185. 'about' => array(),
  186. 'delivery' => array(),
  187. 'payment' => array()
  188. )
  189. )
  190. );
  191.  
  192. function getObjectTree($arrayTree, $parent)
  193. {
  194. //рекурсивная свистопляска
  195.  
  196. foreach ($arrayTree as $name => $node)
  197. {
  198. $$name = new Node($name);
  199. if ($parent) { $parent->appendChild($$name); }
  200. getObjectTree($node, $$name);
  201. }
  202. //если узел лишён родителя, то его нужно вывести
  203. if (!$parent) {return $$name;}
  204. }
  205.  
  206. $parent = NULL;
  207. $root = getObjectTree($arrayTree, $parent);
  208.  
  209. return $root;
  210.  
  211. }
  212. }
  213.  
  214. class View {
  215. const COLUMN_SPACING = 4;
  216.  
  217. function getColumn($node, $width) {
  218. $level = count($node->getAllParents());
  219.  
  220. if ($level == 1) {
  221. $word = " " . $node->getName();
  222. $column[] = str_pad($word, $width);
  223. $column[] = str_pad('', $width);
  224. }
  225. if ($level == 2) {
  226. $word = " -" . $node->getName();
  227. $column[] = str_pad($word, $width);
  228. }
  229. if ($level > 2) {
  230. $indent = ($level-1) * 2;
  231. $word = str_pad(' ', $indent ) . $node->getName();
  232. $column[] = str_pad($word, $width);
  233. }
  234.  
  235. $children = $node->getChildrenNode();
  236. foreach ($children as $child) {
  237. $getColumn = $this->getColumn($child, $width);
  238. $column = array_merge($column,$getColumn);
  239. }
  240.  
  241. return $column;
  242.  
  243. }
  244.  
  245. function getWidthColumn($root) {
  246. //определение ширины колонки
  247. $rootChildren = $root->getChildrenNode();
  248. $widthColumn = array();
  249.  
  250. foreach ($rootChildren as $rootChild) {
  251. //ширина первого пункта меню
  252. $width = mb_strlen($rootChild->getName()) + 2 ;
  253. $allChildrenNode = $rootChild->getAllChildren();
  254.  
  255. foreach ($allChildrenNode as $node) {
  256. $level = count($node->getAllParents());
  257.  
  258. $thisWidthNode = mb_strlen($node->getName()) + (2 * ($level - 1));
  259. $width = max($width,$thisWidthNode);
  260. }
  261. //к ширине строки прибавляется расстояние между колонками 4
  262. $widthColumn[] = $width+self::COLUMN_SPACING;
  263. }
  264. return $widthColumn;
  265. }
  266.  
  267. function getHeightColumn($root){
  268. $heightColumn = 0;
  269. $rootChildren = $root->getChildrenNode();
  270.  
  271.  
  272. foreach ($rootChildren as $rootChild) {
  273.  
  274. //находим пункты меню(кроме первых уровней) данного столбца.
  275. $menuItems = $rootChild->getAllChildren();
  276. //получаем колличество строк в меню
  277. $heightThisColumn = count($menuItems) + 2;
  278. $heightColumn = max($heightColumn, $heightThisColumn);
  279. }
  280.  
  281. return $heightColumn;
  282. }
  283.  
  284. function getTextMenu($root) {
  285. $widthColumn = $this->getWidthColumn($root);
  286. $heightColumn = $this->getHeightColumn($root);
  287.  
  288.  
  289. $children = $root->getChildrenNode();
  290. $countColumn = count($children);
  291. $menu = '';
  292.  
  293. $column = array();
  294. $i = -1;
  295. foreach ($children as $child) {
  296. $i++;
  297. $columns[] = $this->getColumn($child, $widthColumn[$i]);
  298. }
  299.  
  300. for ( $i = 0 ; $i < $heightColumn ; $i++ ) {
  301. for ( $j = 0 ; $j < $countColumn ; $j++ ) {
  302. if (isset($columns[$j][$i])) {
  303. $menu.= $columns[$j][$i];
  304. }else{
  305. $menu.= str_pad('', $widthColumn[$j]);
  306. }
  307. }
  308. $menu .= "\n";
  309. }
  310.  
  311. return $menu;
  312. }
  313.  
  314. function writeMenu(){
  315. $creator = new Creator();
  316. $root = $creator->createTree();
  317. $menu = $this->getTextMenu($root);
  318. return $menu;
  319. }
  320. }
  321.  
  322. //$view = new View;
  323. //echo $view->writeMenu() . "\n";
  324.  
  325.  
  326. //тут тестирую функцию walk
  327. echo "приступить к тесту \n\n\n";
  328. function myFunction($node) {
  329. echo $node->getName() . "\n";
  330. }
  331.  
  332.  
  333. $creator = new Creator;
  334. $root = $creator->createTree();
  335.  
  336. $root->walk('myFunction');
Success #stdin #stdout 0.01s 20520KB
stdin
Standard input is empty
stdout
приступить к тесту 


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