PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/joomla/libraries/gantry5/classes/Gantry/Component/Menu/Item.php

https://gitlab.com/ricardosanchez/prueba
PHP | 398 lines | 249 code | 60 blank | 89 comment | 16 complexity | f552ff13c814dd7cfd3adf1c2f3ad267 MD5 | raw file
  1. <?php
  2. /**
  3. * @package Gantry5
  4. * @author RocketTheme http://www.rockettheme.com
  5. * @copyright Copyright (C) 2007 - 2016 RocketTheme, LLC
  6. * @license Dual License: MIT or GNU/GPLv2 and later
  7. *
  8. * http://opensource.org/licenses/MIT
  9. * http://www.gnu.org/licenses/gpl-2.0.html
  10. *
  11. * Gantry Framework code that extends GPL code is considered GNU/GPLv2 and later
  12. */
  13. namespace Gantry\Component\Menu;
  14. use RocketTheme\Toolbox\ArrayTraits\ArrayAccessWithGetters;
  15. use RocketTheme\Toolbox\ArrayTraits\Export;
  16. /**
  17. * @property string $id
  18. * @property string $type
  19. * @property string $path
  20. * @property string $alias
  21. * @property string $title
  22. * @property string $link
  23. * @property string $parent_id
  24. * @property string $layout
  25. * @property int $browserNav
  26. * @property bool $menu_text
  27. * @property bool $visible
  28. * @property int $group
  29. * @property int $level
  30. */
  31. class Item implements \ArrayAccess, \Iterator, \Serializable, \Countable
  32. {
  33. use ArrayAccessWithGetters, Export;
  34. const VERSION = 1;
  35. protected $items;
  36. protected $menu;
  37. protected $groups = [];
  38. protected $children = [];
  39. protected $url;
  40. protected static $defaults = [
  41. 'id' => 0,
  42. 'type' => 'link',
  43. 'path' => null,
  44. 'alias' => null,
  45. 'title' => null,
  46. 'link' => null,
  47. 'parent_id' => null,
  48. 'layout' => 'list',
  49. 'target' => '_self',
  50. 'dropdown' => '',
  51. 'icon' => '',
  52. 'image' => '',
  53. 'subtitle' => '',
  54. 'hash' => '',
  55. 'class' => '',
  56. 'icon_only' => false,
  57. 'enabled' => true,
  58. 'visible' => true,
  59. 'group' => 0,
  60. 'columns' => [],
  61. 'level' => 0,
  62. 'link_title' => '',
  63. 'anchor_class' => ''
  64. ];
  65. public function __construct(AbstractMenu $menu, $name, array $item = [])
  66. {
  67. $this->menu = $menu;
  68. $tree = explode('/', $name);
  69. $alias = array_pop($tree);
  70. $parent = implode('/', $tree);
  71. // As we always calculate parent (it can change), prevent old one from being inserted.
  72. unset($item['parent_id']);
  73. $this->items = $item + [
  74. 'id' => preg_replace('|[^a-z0-9]|i', '-', $name) ?: 'root',
  75. 'path' => $name,
  76. 'alias' => $alias,
  77. 'title' => ucfirst($alias),
  78. 'link' => $name,
  79. 'parent_id' => $parent != '.' ? $parent : '',
  80. ] + static::$defaults;
  81. }
  82. public function getDropdown()
  83. {
  84. if (!$this->items['dropdown']) {
  85. return count($this->groups()) > 1 ? 'fullwidth' : 'standard';
  86. }
  87. return $this->items['dropdown'];
  88. }
  89. public function serialize()
  90. {
  91. // FIXME: need to create collection class to gather the sibling data.
  92. return serialize([
  93. 'version' => static::VERSION,
  94. 'items' => $this->items,
  95. 'groups' => $this->groups,
  96. 'children' => $this->children,
  97. 'url' => $this->url
  98. ]);
  99. }
  100. public function unserialize($serialized)
  101. {
  102. // FIXME: need to create collection class to gather the sibling data.
  103. $data = unserialize($serialized);
  104. if (!isset($data['version']) && $data['version'] === static::VERSION) {
  105. throw new \UnexpectedValueException('Serialized data is not valid');
  106. }
  107. $this->items = $data['items'];
  108. $this->groups = $data['groups'];
  109. $this->children = $data['children'];
  110. $this->url = $data['url'];
  111. }
  112. /**
  113. * @param string|null|bool $url
  114. * @return string
  115. */
  116. public function url($url = false)
  117. {
  118. if ($url !== false) {
  119. $this->url = $url;
  120. }
  121. return $this->url;
  122. }
  123. /**
  124. * @return AbstractMenu
  125. * @deprecated Need to break relationship to the menu and use a collection instead.
  126. */
  127. protected function menu()
  128. {
  129. return $this->menu;
  130. }
  131. /**
  132. * @return Item
  133. */
  134. public function parent()
  135. {
  136. return $this->menu()[$this->items['parent_id']];
  137. }
  138. public function columnWidth($column)
  139. {
  140. if (isset($this->items['columns'][$column])) {
  141. return $this->items['columns'][$column];
  142. }
  143. return 100 / count($this->groups());
  144. }
  145. public function groups()
  146. {
  147. if ($this->groups) {
  148. $list = [];
  149. foreach ($this->groups as $i => $group) {
  150. $list[$i] = [];
  151. foreach ($group as $path) {
  152. $list[$i][] = $this->menu()[$path];
  153. }
  154. }
  155. return $list;
  156. }
  157. return [$this->children()];
  158. }
  159. public function children()
  160. {
  161. $list = [];
  162. foreach ($this as $child) {
  163. $list[] = $child;
  164. }
  165. return $list;
  166. }
  167. public function hasChildren()
  168. {
  169. return !empty($this->children);
  170. }
  171. public function getGroup($i)
  172. {
  173. $groups = $this->groups();
  174. $i = (int) $i;
  175. return isset($groups[$i]) ? $groups[$i] : [];
  176. }
  177. public function update(array $data)
  178. {
  179. $this->items = array_replace($this->items, $data);
  180. return $this;
  181. }
  182. public function addChild(Item $child)
  183. {
  184. $child->level = $this->level + 1;
  185. $child->parent_id = $this->path;
  186. $this->children[$child->alias] = $child->path;
  187. return $this;
  188. }
  189. public function removeChild(Item $child)
  190. {
  191. unset($this->children[$child->alias]);
  192. return $this;
  193. }
  194. public function sortChildren($ordering)
  195. {
  196. // Array with keys that point to the items.
  197. $children =& $this->children;
  198. if ($children) {
  199. if (is_array($ordering)) {
  200. // Remove extra items from ordering and reorder.
  201. $children = array_replace(array_intersect_key($ordering, $children), $children);
  202. } else {
  203. switch ((string) $ordering) {
  204. case 'abc':
  205. // Alphabetical ordering.
  206. ksort($children, SORT_NATURAL);
  207. break;
  208. case 'cba':
  209. // Reversed alphabetical ordering.
  210. krsort($children, SORT_NATURAL);
  211. break;
  212. }
  213. }
  214. }
  215. return $this;
  216. }
  217. public function reverse()
  218. {
  219. array_reverse($this->children, true);
  220. array_reverse($this->groups, true);
  221. return $this;
  222. }
  223. public function groupChildren(array $groups)
  224. {
  225. // Array with keys that point to the items.
  226. $children =& $this->children;
  227. if ($children) {
  228. $menu = $this->menu();
  229. $ordered = [];
  230. // Create empty groups.
  231. $this->groups = array_fill(0, max(1, count($this->items['columns'])), []);
  232. foreach ($groups as $i => $ordering) {
  233. if (!is_array($ordering)) {
  234. continue;
  235. }
  236. // Get the items for this group with proper ordering.
  237. $group = array_replace(
  238. array_intersect_key($ordering, $children), array_intersect_key($children, $ordering)
  239. );
  240. // Assign each menu items to the group.
  241. $group = array_map(
  242. function($value) use ($i, $menu) {
  243. $item = $menu[$value];
  244. $item->group = $i;
  245. return $value;
  246. },
  247. $group
  248. );
  249. // Update remaining children.
  250. $children = array_diff_key($children, $ordering);
  251. // Build child ordering.
  252. $ordered += $group;
  253. // Add items to the current group.
  254. $this->groups[$i] = $group;
  255. }
  256. if ($children) {
  257. // Add leftover children to the ordered list and to the first group.
  258. $ordered += $children;
  259. $this->groups[0] += $children;
  260. }
  261. // Reorder children by their groups.
  262. $children = $ordered;
  263. }
  264. return $this;
  265. }
  266. // Implements \Iterator
  267. /**
  268. * Returns the current child.
  269. *
  270. * @return Item
  271. */
  272. public function current()
  273. {
  274. return $this->menu()[current($this->children)];
  275. }
  276. /**
  277. * Returns the key of the current child.
  278. *
  279. * @return mixed Returns scalar on success, or NULL on failure.
  280. */
  281. public function key()
  282. {
  283. return key($this->children);
  284. }
  285. /**
  286. * Moves the current position to the next child.
  287. *
  288. * @return void
  289. */
  290. public function next()
  291. {
  292. next($this->children);
  293. }
  294. /**
  295. * Rewinds back to the first child.
  296. *
  297. * @return void
  298. */
  299. public function rewind()
  300. {
  301. reset($this->children);
  302. }
  303. /**
  304. * Count number of children.
  305. *
  306. * @return int
  307. */
  308. public function count()
  309. {
  310. return count($this->children);
  311. }
  312. /**
  313. * This method is called after Iterator::rewind() and Iterator::next() to check if the current position is valid.
  314. *
  315. * @return bool Returns TRUE on success or FALSE on failure.
  316. */
  317. public function valid()
  318. {
  319. return key($this->children) !== null;
  320. }
  321. /**
  322. * Convert object into an array.
  323. *
  324. * @return array
  325. */
  326. public function toArray($withDefaults = true)
  327. {
  328. $items = $this->items;
  329. if (!$withDefaults) {
  330. foreach (static::$defaults as $key => $value) {
  331. if ($items[$key] === $value) {
  332. unset($items[$key]);
  333. }
  334. }
  335. }
  336. return $items;
  337. }
  338. }