<?php declare(strict_types=1); namespace Arcanedev\Html\Entities; use Arcanedev\Html\Entities\Attributes\{AbstractAttribute, ClassAttribute, MiscAttribute}; use ArrayAccess; use Illuminate\Contracts\Support\Arrayable; /** * Class Attributes * * @author ARCANEDEV <arcanedev.maroc@gmail.com> */ class Attributes implements ArrayAccess, Arrayable { /* ----------------------------------------------------------------- | Properties | ----------------------------------------------------------------- */ /** @var array */ protected $items; /* ----------------------------------------------------------------- | Constructor | ----------------------------------------------------------------- */ /** * Attributes constructor. * * @param array $items */ public function __construct(array $items = []) { $this->items = []; $this->setMany($items); } /* ----------------------------------------------------------------- | Main Methods | ----------------------------------------------------------------- */ /** * Make the attribute instance. * * @param array $items * * @return \Arcanedev\Html\Entities\Attributes */ public static function make(array $items = []) { return new static($items); } /** * Set an attribute. * * @param string $name * @param mixed|null $value * * @return static */ public function set($name, $value = null) { $attribute = static::makeAttribute($name, $value); $this->offsetSet($attribute->name(), $attribute); return $this; } /** * Make a new attribute. * * @param string $name * @param mixed $value * * @return mixed */ protected static function makeAttribute(string $name, $value) { switch ($name) { case 'class': return new ClassAttribute($value); default: return new MiscAttribute($name, $value); } } /** * Get an attribute. * * @param string $key * @param mixed $default * * @return \Arcanedev\Html\Entities\Attributes\AbstractAttribute|mixed */ public function get($key, $default = null) { return $this->offsetExists($key) ? $this->offsetGet($key) : value($default); } /** * @param string|array $keys * * @return static */ public function forget($keys) { foreach ((array) $keys as $key) { $this->offsetUnset($key); } return $this; } /** * Determine if an item exists in the collection by key. * * @param mixed $keys * * @return bool */ public function has(...$keys) { foreach ($keys as $value) { if ( ! $this->offsetExists($value)) return false; } return true; } /** * Set many attributes. * * @param iterable $attributes * * @return static */ public function setMany($attributes) { foreach ($attributes as $attribute => $value) { if (is_int($attribute)) { $attribute = $value; $value = null; } $this->set($attribute, $value); } return $this; } /** * Add a class. * * @param iterable|string $class * * @return static */ public function addClass($class) { return $this->set('class', $class); } /** * Render the attributes. * * @return string */ public function render() { if ($this->isNotEmpty()) return implode(' ', array_map(function (AbstractAttribute $attribute) { return $attribute->render(); }, $this->items)); return ''; } /** * Convert the attributes to array. * * @return array */ public function toArray() { return array_map(function (AbstractAttribute $attribute) { return $attribute->value(); }, $this->items); } /** * Check if the container is empty. * * @return bool */ public function isEmpty() { return empty($this->items); } /** * Check if the container is not empty. * * @return bool */ public function isNotEmpty() { return ! $this->isEmpty(); } /** * Get the class attribute. * * @return \Arcanedev\Html\Entities\Attributes\ClassAttribute|null */ public function classList() { return $this->get('class'); } /* ----------------------------------------------------------------- | Other Methods | ----------------------------------------------------------------- */ /** * Determine if an item exists at an offset. * * @param mixed $key * * @return bool */ public function offsetExists($key): bool { return array_key_exists($key, $this->items); } /** * Get an item at a given offset. * * @param mixed $key * * @return mixed */ public function offsetGet($key): mixed { return $this->items[$key]; } /** * Set the item at a given offset. * * @param mixed $key * @param mixed $value * * @return void */ public function offsetSet($key, $value): void { $this->items[$key] = $value; } /** * Unset the item at a given offset. * * @param string $key * * @return void */ public function offsetUnset($key): void { unset($this->items[$key]); } }