Your IP : 18.191.167.138


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/ui/lib/buttons/
Upload File :
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/ui/lib/buttons/buttonattributes.php

<?php

namespace Bitrix\UI\Buttons;

use Bitrix\Main\Type\Contract\Arrayable;
use Bitrix\Main\Web\Json;

final class ButtonAttributes implements \ArrayAccess, \IteratorAggregate, \Countable, Arrayable
{
	const JSON_OPTIONS_DATA_ATTR = 'data-json-options';

	/** @var array */
	private $attributes = [];
	/** @var array */
	private $dataAttributes = [];

	public function __construct(array $attributes = [])
	{
		$this->setAttributes($attributes);
	}

	public function setAttributes(array $attributes)
	{
		list($this->dataAttributes, $this->attributes) = self::splitDataAttributesAndAnother($attributes);

		return $this;
	}

	/**
	 * @param string $name
	 * @param mixed|null $defaultValue
	 *
	 * @return mixed|null
	 */
	public function getAttribute($name, $defaultValue = null)
	{
		return isset($this[$name])? $this[$name] : $defaultValue;
	}

	/**
	 * @param string $name
	 * @param mixed|null $value
	 *
	 * @return $this
	 */
	public function addDataAttribute($name, $value = null)
	{
		$this[self::addDataPrefix($name)] = $value;

		return $this;
	}

	/**
	 * @param string $name
	 * @param mixed|null $defaultValue
	 *
	 * @return mixed|null
	 */
	public function getDataAttribute($name, $defaultValue = null)
	{
		return $this->getAttribute(self::addDataPrefix($name), $defaultValue);
	}

	/**
	 * @return array
	 */
	public function getDataAttributes()
	{
		return $this->dataAttributes;
	}

	public function addJsonOption($key, $value)
	{
		if (!isset($this[self::JSON_OPTIONS_DATA_ATTR]))
		{
			$this[self::JSON_OPTIONS_DATA_ATTR] = [];
		}

		$this[self::JSON_OPTIONS_DATA_ATTR][$key] = $value;

		return $this;
	}

	public function removeJsonOption($key)
	{
		unset($this[self::JSON_OPTIONS_DATA_ATTR][$key]);

		return $this;
	}

	public function setJsonOptions(array $options)
	{
		$this[self::JSON_OPTIONS_DATA_ATTR] = $options;

		return $this;
	}

	public function getJsonOptions()
	{
		return isset($this[self::JSON_OPTIONS_DATA_ATTR])? $this[self::JSON_OPTIONS_DATA_ATTR] : null;
	}

	/**
	 * @param string $className
	 *
	 * @return $this
	 */
	public function addClass($className)
	{
		if (!isset($this['class']))
		{
			$this['class'] = [];
		}

		if (!in_array($className, $this['class'], true))
		{
			$this['class'][] = $className;
		}

		return $this;
	}

	/**
	 * @param string $className
	 *
	 * @return bool
	 */
	public function hasClass($className)
	{
		return isset($this['class']) && in_array($className, $this['class'], true);
	}

	public function setClassList(array $classList)
	{
		$this['class'] = $classList;

		return $this;
	}

	/**
	 * @param string $className
	 *
	 * @return $this
	 */
	public function removeClass($className)
	{
		if (!isset($this['class']))
		{
			$this['class'] = [];
		}

		$index = array_search($className, $this['class'], true);
		if ($index !== false)
		{
			unset($this['class'][$index]);
		}

		return $this;
	}

	/**
	 * Retrieve an external iterator
	 * @link https://php.net/manual/en/iteratoraggregate.getiterator.php
	 * @return \Traversable An instance of an object implementing <b>Iterator</b> or
	 * <b>Traversable</b>
	 * @since 5.0.0
	 */
	public function getIterator()
	{
		return new \ArrayIterator($this->toArray());
	}

	/**
	 * Whether a offset exists
	 * @link https://php.net/manual/en/arrayaccess.offsetexists.php
	 *
	 * @param mixed $offset <p>
	 * An offset to check for.
	 * </p>
	 *
	 * @return boolean true on success or false on failure.
	 * </p>
	 * <p>
	 * The return value will be casted to boolean if non-boolean was returned.
	 * @since 5.0.0
	 */
	public function offsetExists($offset)
	{
		$offset = mb_strtolower($offset);

		$asAttribute = isset($this->attributes[$offset]) || array_key_exists($offset, $this->attributes);
		if ($asAttribute)
		{
			return true;
		}

		if (!self::hasDataPrefix($offset))
		{
			return false;
		}

		$offset = self::deleteDataPrefix($offset);

		return isset($this->dataAttributes[$offset]) || array_key_exists($offset, $this->dataAttributes);
	}

	/**
	 * Offset to retrieve
	 * @link https://php.net/manual/en/arrayaccess.offsetget.php
	 *
	 * @param mixed $offset <p>
	 * The offset to retrieve.
	 * </p>
	 *
	 * @return mixed Can return all value types.
	 * @since 5.0.0
	 */
	public function &offsetGet($offset)
	{
		$offset = mb_strtolower($offset);
		if (isset($this->attributes[$offset]) || array_key_exists($offset, $this->attributes))
		{
			return $this->attributes[$offset];
		}

		if (!self::hasDataPrefix($offset))
		{
			return null;
		}

		$offset = self::deleteDataPrefix($offset);
		if (isset($this->dataAttributes[$offset]) || array_key_exists($offset, $this->dataAttributes))
		{
			return $this->dataAttributes[$offset];
		}

		return null;
	}

	/**
	 * Offset to set
	 * @link https://php.net/manual/en/arrayaccess.offsetset.php
	 *
	 * @param mixed $offset <p>
	 * The offset to assign the value to.
	 * </p>
	 * @param mixed $value <p>
	 * The value to set.
	 * </p>
	 *
	 * @return void
	 * @since 5.0.0
	 */
	public function offsetSet($offset, $value)
	{
		if($offset === null)
		{
			$this->attributes[] = $value;
		}
		else
		{
			$offset = mb_strtolower($offset);
			if (self::hasDataPrefix($offset))
			{
				$this->dataAttributes[self::deleteDataPrefix($offset)] = $value;
			}
			else
			{
				$this->attributes[$offset] = $value;
			}
		}
	}

	/**
	 * Offset to unset
	 * @link https://php.net/manual/en/arrayaccess.offsetunset.php
	 *
	 * @param mixed $offset <p>
	 * The offset to unset.
	 * </p>
	 *
	 * @return void
	 * @since 5.0.0
	 */
	public function offsetUnset($offset)
	{
		$offset = mb_strtolower($offset);
		if (isset($this->attributes[$offset]) || array_key_exists($offset, $this->attributes))
		{
			unset($this->attributes[$offset]);

			return;
		}

		if (!self::hasDataPrefix($offset))
		{
			return null;
		}

		$offset = self::deleteDataPrefix($offset);
		if (isset($this->dataAttributes[$offset]) || array_key_exists($offset, $this->dataAttributes))
		{
			unset($this->dataAttributes[$offset]);
		}
	}

	/**
	 * Count elements of an object
	 * @link https://php.net/manual/en/countable.count.php
	 * @return int The custom count as an integer.
	 * </p>
	 * <p>
	 * The return value is cast to an integer.
	 * @since 5.1.0
	 */
	public function count()
	{
		return count($this->dataAttributes) + count($this->attributes);
	}

	/**
	 * @return string
	 */
	public function toString()
	{
		return (string)$this;
	}

	/**
	 * @return string
	 */
	public function __toString()
	{
		$string = '';
		foreach ($this as $key => $value)
		{
			if (is_int($key))
			{
				$string .= "{$value} ";
			}
			else
			{
				if ($key === 'class')
				{
					$value = self::convertClassesToString($value);
				}
				elseif ($key === 'style')
				{
					$value = self::convertStylesToString($value);
				}
				elseif ($key === self::JSON_OPTIONS_DATA_ATTR)
				{
					$value = Json::encode($this->getJsonOptions());
				}

				$value = htmlspecialcharsbx($value);
				$string .= "{$key}=\"{$value}\" ";
			}
		}

		return $string;
	}

	protected static function convertClassesToString($classes)
	{
		if (is_string($classes))
		{
			return $classes;
		}

		return implode(' ', $classes);
	}

	protected static function convertStylesToString($styles)
	{
		if (is_string($styles))
		{
			return $styles;
		}

		$string = '';
		foreach ($styles as $name => $value)
		{
			$string .= "{$name}:{$value};";
		}

		return $string;
	}

	/**
	 * @return array
	 */
	public function toArray()
	{
		return array_merge(
			$this->attributes,
			self::convertDataAttributesToAttributes($this->dataAttributes)
		);
	}

	protected static function addDataPrefix($name)
	{
		return "data-{$name}";
	}

	protected static function hasDataPrefix($name)
	{
		return is_string($name) && mb_substr($name, 0, 5) === 'data-';
	}

	protected static function deleteDataPrefix($name)
	{
		if (self::hasDataPrefix($name))
		{
			return mb_substr($name, 5);
		}

		return $name;
	}

	protected static function convertDataAttributesToAttributes(array $dataAttributes)
	{
		$attributes = [];
		foreach ($dataAttributes as $name => $attribute)
		{
			$attributes[self::addDataPrefix($name)] = $attribute;
		}

		return $attributes;
	}

	protected static function splitDataAttributesAndAnother(array $attributes)
	{
		$anotherAttributes = $dataAttributes = [];
		foreach ($attributes as $name => $attribute)
		{
			$name = mb_strtolower($name);
			if (self::hasDataPrefix($name))
			{
				$dataAttributes[mb_substr($name, 5)] = $attribute;
			}
			else
			{
				$anotherAttributes[$name] = $attribute;
			}
		}

		return [$dataAttributes, $anotherAttributes];
	}
}