name = (string) $name; $this->factory = $factory; } /** * setFactory * * @param FactoryInterface $factory * * @return ItemInterface */ public function setFactory(FactoryInterface $factory) { $this->factory = $factory; return $this; } public function getName() { return $this->name; } public function setName($name) { if ($this->name === $name) { return $this; } $parent = $this->getParent(); if (null !== $parent && isset($parent[$name])) { throw new \InvalidArgumentException('Cannot rename item, name is already used by sibling.'); } $oldName = $this->name; $this->name = $name; if (null !== $parent) { $names = \array_keys($parent->getChildren()); $items = \array_values($parent->getChildren()); $offset = \array_search($oldName, $names); $names[$offset] = $name; $parent->setChildren(\array_combine($names, $items)); } return $this; } public function getUri() { return $this->uri; } public function setUri($uri) { $this->uri = $uri; return $this; } public function getLabel() { return (null !== $this->label) ? $this->label : $this->name; } public function setLabel($label) { $this->label = $label; return $this; } public function getAttributes() { return $this->attributes; } public function setAttributes(array $attributes) { $this->attributes = $attributes; return $this; } public function getAttribute($name, $default = null) { if (isset($this->attributes[$name])) { return $this->attributes[$name]; } return $default; } public function setAttribute($name, $value) { $this->attributes[$name] = $value; return $this; } public function getLinkAttributes() { return $this->linkAttributes; } public function setLinkAttributes(array $linkAttributes) { $this->linkAttributes = $linkAttributes; return $this; } public function getLinkAttribute($name, $default = null) { if (isset($this->linkAttributes[$name])) { return $this->linkAttributes[$name]; } return $default; } public function setLinkAttribute($name, $value) { $this->linkAttributes[$name] = $value; return $this; } public function getChildrenAttributes() { return $this->childrenAttributes; } public function setChildrenAttributes(array $childrenAttributes) { $this->childrenAttributes = $childrenAttributes; return $this; } public function getChildrenAttribute($name, $default = null) { if (isset($this->childrenAttributes[$name])) { return $this->childrenAttributes[$name]; } return $default; } public function setChildrenAttribute($name, $value) { $this->childrenAttributes[$name] = $value; return $this; } public function getLabelAttributes() { return $this->labelAttributes; } public function setLabelAttributes(array $labelAttributes) { $this->labelAttributes = $labelAttributes; return $this; } public function getLabelAttribute($name, $default = null) { if (isset($this->labelAttributes[$name])) { return $this->labelAttributes[$name]; } return $default; } public function setLabelAttribute($name, $value) { $this->labelAttributes[$name] = $value; return $this; } public function getExtras() { return $this->extras; } public function setExtras(array $extras) { $this->extras = $extras; return $this; } public function getExtra($name, $default = null) { if (isset($this->extras[$name])) { return $this->extras[$name]; } return $default; } public function setExtra($name, $value) { $this->extras[$name] = $value; return $this; } public function getDisplayChildren() { return $this->displayChildren; } public function setDisplayChildren($bool) { $this->displayChildren = (bool) $bool; return $this; } public function isDisplayed() { return $this->display; } public function setDisplay($bool) { $this->display = (bool) $bool; return $this; } public function addChild($child, array $options = []) { if (!$child instanceof ItemInterface) { $child = $this->factory->createItem($child, $options); } elseif (null !== $child->getParent()) { throw new \InvalidArgumentException('Cannot add menu item as child, it already belongs to another menu (e.g. has a parent).'); } $child->setParent($this); $this->children[$child->getName()] = $child; return $child; } public function getChild($name) { return isset($this->children[$name]) ? $this->children[$name] : null; } public function reorderChildren($order) { if (count($order) != $this->count()) { throw new \InvalidArgumentException('Cannot reorder children, order does not contain all children.'); } $newChildren = []; foreach ($order as $name) { if (!isset($this->children[$name])) { throw new \InvalidArgumentException('Cannot find children named ' . $name); } $child = $this->children[$name]; $newChildren[$name] = $child; } $this->setChildren($newChildren); return $this; } public function copy() { $newMenu = clone $this; $newMenu->setChildren([]); $newMenu->setParent(null); foreach ($this->getChildren() as $child) { $newMenu->addChild($child->copy()); } return $newMenu; } public function getLevel() { return $this->parent ? $this->parent->getLevel() + 1 : 0; } public function getRoot() { $obj = $this; do { $found = $obj; } while ($obj = $obj->getParent()); return $found; } public function isRoot() { return null === $this->parent; } public function getParent() { return $this->parent; } public function setParent(ItemInterface $parent = null) { if ($parent === $this) { throw new \InvalidArgumentException('Item cannot be a child of itself'); } $this->parent = $parent; return $this; } public function getChildren() { return $this->children; } public function setChildren(array $children) { $this->children = $children; return $this; } public function removeChild($name) { $name = $name instanceof ItemInterface ? $name->getName() : $name; if (isset($this->children[$name])) { // unset the child and reset it so it looks independent $this->children[$name]->setParent(null); unset($this->children[$name]); } return $this; } public function getFirstChild() { return \reset($this->children); } public function getLastChild() { return \end($this->children); } public function hasChildren() { foreach ($this->children as $child) { if ($child->isDisplayed()) { return true; } } return false; } public function setCurrent($bool) { $this->isCurrent = $bool; return $this; } public function isCurrent() { return $this->isCurrent; } public function isLast() { // if this is root, then return false if ($this->isRoot()) { return false; } return $this->getParent()->getLastChild() === $this; } public function isFirst() { // if this is root, then return false if ($this->isRoot()) { return false; } return $this->getParent()->getFirstChild() === $this; } public function actsLikeFirst() { // root items are never "marked" as first if ($this->isRoot()) { return false; } // A menu acts like first only if it is displayed if (!$this->isDisplayed()) { return false; } // if we're first and visible, we're first, period. if ($this->isFirst()) { return true; } $children = $this->getParent()->getChildren(); foreach ($children as $child) { // loop until we find a visible menu. If its this menu, we're first if ($child->isDisplayed()) { return $child->getName() === $this->getName(); } } return false; } public function actsLikeLast() { // root items are never "marked" as last if ($this->isRoot()) { return false; } // A menu acts like last only if it is displayed if (!$this->isDisplayed()) { return false; } // if we're last and visible, we're last, period. if ($this->isLast()) { return true; } $children = \array_reverse($this->getParent()->getChildren()); foreach ($children as $child) { // loop until we find a visible menu. If its this menu, we're first if ($child->isDisplayed()) { return $child->getName() === $this->getName(); } } return false; } /** * Implements Countable */ public function count() { return \count($this->children); } /** * Implements IteratorAggregate */ public function getIterator() { return new \ArrayIterator($this->children); } /** * Implements ArrayAccess */ public function offsetExists($name) { return isset($this->children[$name]); } /** * Implements ArrayAccess */ public function offsetGet($name) { return $this->getChild($name); } /** * Implements ArrayAccess */ public function offsetSet($name, $value) { return $this->addChild($name)->setLabel($value); } /** * Implements ArrayAccess */ public function offsetUnset($name) { $this->removeChild($name); } }