* @package zin * @version $Id * @link https://www.zentao.net */ namespace zin\utils; /** * Manage classname list for html element and widgets */ class classlist { /** * Store classname list, key => value * * @access private * @var array */ private array $list = array(); /** * Create classname instance * * @access public * @param array ...$list - A string or a class name list */ public function __construct(/* ...$list */) { $list = func_get_args(); if(!empty($list)) $this->set($list); } /** * Convert classnames to string * * @access public * @return string */ public function __toString(): string { return $this->toStr(); } /** * Create classname instance * * Example: * * // Set class names * $classlist = new classlist(); * $classlist->set('btn primary rounded'); * * // Set multiple classnames by string list * $classlist->set(array('btn', 'primary', 'rounded')); * * // Set multiple classnames by a mapped array * $classlist->set(array('btn' => true, 'primary' => true, 'rounded' => $isRounded)); * * @access public * @param string|array|null $list - A string or a class name list * @param bool $reset * @return classlist */ public function set(string|array|null $list, bool $reset = false): classlist { $this->list = static::parse($list, $reset ? array() : $this->list); return $this; } /** * Add classnames * * Example: * * $classlist = new classlist(); * $classlist->add('btn primary rounded'); * * // Add multiple classnames by string list * $classlist->add('btn', 'primary', 'rounded'); * * @access public * @param array ...$list - classname string joined by space or string array * @return classlist */ public function add(/* ...$list */) { return $this->set(func_get_args()); } /** * Remove classnames * * Example: * * $classlist = new classlist('btn primary rounded'); * $classlist->remove('btn primary'); * * // Add multiple classnames by string list * $classlist->remove('btn', 'primary'); * * @access public * @param array|string $list - classname string joined by space or string array * @return classlist */ public function remove(array|string $list): classlist { if(is_string($list)) $list = explode(' ', $list); foreach($list as $name) { if(!is_string($name)) continue; $name = trim($name); if(!strlen($name)) continue; $this->list[$name] = false; } return $this; } /** * Toggle classname * * Example: * * $classlist = new classlist('btn'); * $classlist->toggle('btn'); // class list is "" * * // Toggle class name by flag * $classlist->toggle('primary', true); // class list is "primary" * * @access public * @param string $name - classname string * @return classlist */ public function toggle(string $name, bool|null $toggle = null): classlist { $name = trim($name); if(strlen($name)) { if($toggle === null) $toggle = !$this->has($name); $this->list[$name] = $toggle; } return $this; } /** * Check whether has specific class name * * Example: * * $classlist = new classlist('btn primary rounded'); * echo $classlist->has('btn'); // Output true * * // Check multiple names * echo $classlist->has('btn primary'); // Output true */ public function has(array|string $list): bool { if(is_string($list)) $list = explode(' ', $list); foreach($list as $name) { if(!is_string($name)) continue; $name = trim($name); if(!strlen($name)) continue; if(!isset($this->list[$name]) || !$this->list[$name]) return false; } return true; } public function clear() { $this->list = array(); } /** * Convert classnames to string * * @access public * @return string */ public function toStr(): string { $names = array(); foreach($this->list as $name => $toggle) { if(!$toggle) continue; $name = trim($name); if(!strlen($name)) continue; $names[] = $name; } return implode(' ', $names); } /** * Get class names count * * @access public * @return int */ public function count(): int { return count($this->list); } public function toJSON(): array { return $this->list; } public static function format(mixed ...$classList): string { return implode(' ', array_keys(static::parse($classList))); } public static function parseList(mixed ...$classList): array { $map = static::parse($classList); return array_keys($map); } public static function parse(mixed $classList, array|string|object|null $currenMap = null): array { $currenMap = is_null($currenMap) ? array() : static::parse($currenMap); if(is_string($classList)) { $classList = explode(' ', $classList); foreach($classList as $name) { $name = trim($name); if(!strlen($name)) continue; $currenMap[$name] = true; } return $currenMap; } if(is_object($classList)) $classList = get_object_vars($classList); if(!is_array($classList)) return $currenMap; foreach($classList as $key => $value) { if(is_string($key)) { if($value && !isset($currenMap[$key])) $currenMap[$key] = true; else if(!$value && isset($currenMap[$key])) unset($currenMap[$key]); continue; } $currenMap = static::parse($value, $currenMap); } return $currenMap; } }