Files
Chamilo/vendor/knplabs/knp-menu/src/Knp/Menu/MenuItem.php
2025-04-10 12:24:57 +02:00

628 lines
13 KiB
PHP

<?php
namespace Knp\Menu;
/**
* Default implementation of the ItemInterface
*/
class MenuItem implements ItemInterface
{
/**
* Name of this menu item (used for id by parent menu)
*
* @var string
*/
protected $name;
/**
* Label to output, name is used by default
*
* @var string|null
*/
protected $label;
/**
* Attributes for the item link
*
* @var array
*/
protected $linkAttributes = [];
/**
* Attributes for the children list
*
* @var array
*/
protected $childrenAttributes = [];
/**
* Attributes for the item text
*
* @var array
*/
protected $labelAttributes = [];
/**
* Uri to use in the anchor tag
*
* @var string|null
*/
protected $uri;
/**
* Attributes for the item
*
* @var array
*/
protected $attributes = [];
/**
* Extra stuff associated to the item
*
* @var array
*/
protected $extras = [];
/**
* Whether the item is displayed
*
* @var bool
*/
protected $display = true;
/**
* Whether the children of the item are displayed
*
* @var bool
*/
protected $displayChildren = true;
/**
* Child items
*
* @var ItemInterface[]
*/
protected $children = [];
/**
* Parent item
*
* @var ItemInterface|null
*/
protected $parent;
/**
* whether the item is current. null means unknown
*
* @var bool|null
*/
protected $isCurrent;
/**
* @var FactoryInterface
*/
protected $factory;
/**
* Class constructor
*
* @param string $name The name of this menu, which is how its parent will
* reference it. Also used as label if label not specified
* @param FactoryInterface $factory
*/
public function __construct($name, FactoryInterface $factory)
{
if (null === $name) {
@trigger_error('Passing a null name is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
}
$this->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);
}
}