Your IP : 216.73.216.81


Current Path : /srv/web/sites/trentinoplant.it/httpdocs/vendor1/phpgt/dom/src/
Upload File :
Current File : /srv/web/sites/trentinoplant.it/httpdocs/vendor1/phpgt/dom/src/DOMTokenList.php

<?php
namespace Gt\Dom;

use Countable;
use Gt\PropFunc\MagicProp;
use Iterator;

/**
 * The DOMTokenList interface represents a set of space-separated tokens. Such
 * a set is returned by Element.classList, HTMLLinkElement.relList,
 * HTMLAnchorElement.relList, HTMLAreaElement.relList,
 * HTMLIframeElement.sandbox, or HTMLOutputElement.htmlFor. It is indexed
 * beginning with 0 as with JavaScript Array objects. DOMTokenList is always
 * case-sensitive.
 *
 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList
 *
 * @property-read int $length Is an integer representing the number of objects stored in the object.
 * @property string $value A stringifier property that returns the value of the list as a DOMString.
 * @implements Iterator<int, string>
 */
class DOMTokenList implements Countable, Iterator {
	use MagicProp;

	/** @var callable Return an indexed array of tokens */
	private $accessCallback;
	/** @var callable Variadic string parameters, void return */
	private $mutateCallback;
	private int $iteratorIndex;

	protected function __construct(
		callable $accessCallback,
		callable $mutateCallback
	) {
		$this->accessCallback = $accessCallback;
		$this->mutateCallback = $mutateCallback;
		$this->iteratorIndex = 0;
	}

	/** @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/length */
	protected function __prop_get_length():int {
		return count($this->callAccessor());
	}

	/** https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/value */
	protected function __prop_get_value():string {
		return implode(" ", $this->callAccessor());
	}

	/** https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/value */
	protected function __prop_set_value(string $value):void {
		$tokens = explode(" ", $value);
		$this->accessCallback = fn() => $tokens;
		$this->callMutator(...$tokens);
	}

	/**
	 * The item() method of the DOMTokenList interface returns an item in
	 * the list by its index.
	 *
	 * @param int $index A int representing the index of the item you want
	 * to return.
	 * @return string A DOMString representing the returned item. It returns
	 * null if the number is greater than or equal to the length of the
	 * list.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/item
	 */
	public function item(int $index):string {
		return $this->callAccessor()[$index];
	}

	/**
	 * The contains() method of the DOMTokenList interface returns a
	 * Boolean — true if the underlying list contains the given token,
	 * otherwise false.
	 *
	 * @param string $token A DOMString representing the token you want to
	 * check for the existence of in the list.
	 * @return bool A Boolean, which is true if the calling list contains
	 * token, otherwise false.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/contains
	 */
	public function contains(string $token):bool {
		return in_array($token, $this->callAccessor());
	}

	/**
	 * The add() method of the DOMTokenList interface adds the given token
	 * to the list.
	 *
	 * @param string ...$tokens A DOMString representing the token (or
	 * tokens) to add to the tokenList.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/add
	 */
	public function add(string...$tokens):void {
		$existing = $this->callAccessor();
		$newTokens = array_merge($existing, $tokens);
		$newTokens = array_unique($newTokens);
		$this->callMutator(...$newTokens);
	}

	/**
	 * The remove() method of the DOMTokenList interface removes the
	 * specified tokens from the list.
	 *
	 * @param string ...$tokens A DOMString representing the token you want
	 * to remove from the list. If the string is not in the list, no error
	 * is thrown, and nothing happens.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/remove
	 */
	public function remove(string...$tokens):void {
		$currentTokens = $this->callAccessor();
		foreach($tokens as $token) {
			$key = array_search($token, $currentTokens);
			if($key === false) {
				continue;
			}

			unset($currentTokens[$key]);
		}

		$currentTokens = array_values($currentTokens);
		$this->accessCallback = fn() => $currentTokens;
		$this->callMutator(...$currentTokens);
	}

	/**
	 * The replace() method of the DOMTokenList interface replaces an
	 * existing token with a new token. If the first token doesn't exist,
	 * replace() returns false immediately, without adding the new token to
	 * the token list.
	 *
	 * @param string $oldToken
	 * @param string $newToken
	 * @return bool A boolean value, which is true if oldToken was
	 * successfully replaced, or false if not.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/replace
	 */
	public function replace(string $oldToken, string $newToken):bool {
		$currentTokens = $this->callAccessor();
		$key = array_search($oldToken, $currentTokens);
		if($key === false) {
			return false;
		}

		$currentTokens[$key] = $newToken;

		$currentTokens = array_values($currentTokens);
		$this->accessCallback = fn() => $currentTokens;
		$this->callMutator(...$currentTokens);
		return true;
	}

	/**
	 * The toggle() method of the DOMTokenList interface removes a given
	 * token from the list and returns false. If token doesn't exist it's
	 * added and the function returns true.
	 *
	 * @param string $token A DOMString representing the token you want to
	 * toggle.
	 * @param ?bool $force A Boolean that, if included, turns the toggle
	 * into a one way-only operation. If set to false, then token will only
	 * be removed, but not added. If set to true, then token will only be
	 * added, but not removed.
	 * @return bool A Boolean indicating whether token is in the list after
	 * the call.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle
	 */
	public function toggle(string $token, bool $force = null):bool {
		/** @var ?bool $addRemove True to add, false to remove */
		$addRemove = $force;

		$currentTokens = $this->callAccessor();
		$key = array_search($token, $currentTokens);
		if($key === false) {
			if($force !== false) {
				$addRemove = true;
			}
		}
		else {
			if($force !== true) {
				$addRemove = false;
			}
		}

		if($addRemove) {
			$this->add($token);
			return true;
		}
		else {
			$this->remove($token);
			return false;
		}
	}

	/**
	 * The DOMTokenList.entries() method returns an iterator allowing you to
	 * go through all key/value pairs contained in this object. The values
	 * are DOMString objects, each representing a single token.
	 *
	 * @return iterable<int, string> Each element represents the key and
	 * value, for example: "0,first"
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/entries
	 */
	public function entries():iterable {
		foreach($this->callAccessor() as $key => $value) {
			yield $key => $value;
		}
	}

	/**
	 * The forEach() method of the DOMTokenList interface calls the callback
	 * given in parameter once for each value pair in the list, in
	 * insertion order.
	 *
	 * @param callable $callback Function to execute for each element,
	 * eventually taking three arguments:
	 * 1) currentValue - The current element being processed in the array.
	 * 2) currentIndex - The index of the current element being processed in
	 * the array.
	 * 3) listObj - The array that forEach() is being applied to.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/forEach
	 */
	public function forEach(callable $callback):void {
		foreach($this as $value) {
			call_user_func($callback, $value);
		}
	}

	/**
	 * The keys() method of the DOMTokenList interface returns an iterator
	 * allowing to go through all keys contained in this object. The keys
	 * are of type unsigned integer.
	 *
	 * @return iterable<int> Returns an iterator.
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/keys
	 */
	public function keys():iterable {
		$this->rewind();
		while($this->valid()) {
			yield $this->key();
			$this->next();
		}
	}

	/**
	 * The values() method of the DOMTokenList interface returns an iterator
	 * allowing developers to go through all values contained in the
	 * DOMTokenList. The individual values are DOMString objects.
	 *
	 * @return iterable<string>
	 * @link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/values
	 */
	public function values():iterable {
		foreach($this as $value) {
			yield $value;
		}
	}

	public function count():int {
		return $this->length;
	}

	/** @return string[] */
	private function callAccessor():array {
		$values = call_user_func($this->accessCallback);
		return array_filter($values);
	}

	private function callMutator(string...$values):void {
		call_user_func_array($this->mutateCallback, $values);
	}

	public function current():string {
		return $this->callAccessor()[$this->iteratorIndex];
	}

	public function next():void {
		$this->iteratorIndex++;
	}

	public function key():int {
		return $this->iteratorIndex;
	}

	public function valid():bool {
		$tokens = $this->callAccessor();
		return isset($tokens[$this->iteratorIndex]);
	}

	public function rewind():void {
		$this->iteratorIndex = 0;
	}
}