Viewing file: ComponentAttributeBag.php (9.87 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
namespace Illuminate\View;
use ArrayAccess; use ArrayIterator; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Arr; use Illuminate\Support\HtmlString; use Illuminate\Support\Str; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; use IteratorAggregate;
class ComponentAttributeBag implements ArrayAccess, Htmlable, IteratorAggregate { use Conditionable, Macroable;
/** * The raw array of attributes. * * @var array */ protected $attributes = [];
/** * Create a new component attribute bag instance. * * @param array $attributes * @return void */ public function __construct(array $attributes = []) { $this->attributes = $attributes; }
/** * Get the first attribute's value. * * @param mixed $default * @return mixed */ public function first($default = null) { return $this->getIterator()->current() ?? value($default); }
/** * Get a given attribute from the attribute array. * * @param string $key * @param mixed $default * @return mixed */ public function get($key, $default = null) { return $this->attributes[$key] ?? value($default); }
/** * Determine if a given attribute exists in the attribute array. * * @param string $key * @return bool */ public function has($key) { return array_key_exists($key, $this->attributes); }
/** * Only include the given attribute from the attribute array. * * @param mixed $keys * @return static */ public function only($keys) { if (is_null($keys)) { $values = $this->attributes; } else { $keys = Arr::wrap($keys);
$values = Arr::only($this->attributes, $keys); }
return new static($values); }
/** * Exclude the given attribute from the attribute array. * * @param mixed|array $keys * @return static */ public function except($keys) { if (is_null($keys)) { $values = $this->attributes; } else { $keys = Arr::wrap($keys);
$values = Arr::except($this->attributes, $keys); }
return new static($values); }
/** * Filter the attributes, returning a bag of attributes that pass the filter. * * @param callable $callback * @return static */ public function filter($callback) { return new static(collect($this->attributes)->filter($callback)->all()); }
/** * Return a bag of attributes that have keys starting with the given value / pattern. * * @param string|string[] $needles * @return static */ public function whereStartsWith($needles) { return $this->filter(function ($value, $key) use ($needles) { return Str::startsWith($key, $needles); }); }
/** * Return a bag of attributes with keys that do not start with the given value / pattern. * * @param string|string[] $needles * @return static */ public function whereDoesntStartWith($needles) { return $this->filter(function ($value, $key) use ($needles) { return ! Str::startsWith($key, $needles); }); }
/** * Return a bag of attributes that have keys starting with the given value / pattern. * * @param string|string[] $needles * @return static */ public function thatStartWith($needles) { return $this->whereStartsWith($needles); }
/** * Exclude the given attribute from the attribute array. * * @param mixed|array $keys * @return static */ public function exceptProps($keys) { $props = [];
foreach ($keys as $key => $defaultValue) { $key = is_numeric($key) ? $defaultValue : $key;
$props[] = $key; $props[] = Str::kebab($key); }
return $this->except($props); }
/** * Conditionally merge classes into the attribute bag. * * @param mixed|array $classList * @return static */ public function class($classList) { $classList = Arr::wrap($classList);
return $this->merge(['class' => Arr::toCssClasses($classList)]); }
/** * Merge additional attributes / values into the attribute bag. * * @param array $attributeDefaults * @param bool $escape * @return static */ public function merge(array $attributeDefaults = [], $escape = true) { $attributeDefaults = array_map(function ($value) use ($escape) { return $this->shouldEscapeAttributeValue($escape, $value) ? e($value) : $value; }, $attributeDefaults);
[$appendableAttributes, $nonAppendableAttributes] = collect($this->attributes) ->partition(function ($value, $key) use ($attributeDefaults) { return $key === 'class' || (isset($attributeDefaults[$key]) && $attributeDefaults[$key] instanceof AppendableAttributeValue); });
$attributes = $appendableAttributes->mapWithKeys(function ($value, $key) use ($attributeDefaults, $escape) { $defaultsValue = isset($attributeDefaults[$key]) && $attributeDefaults[$key] instanceof AppendableAttributeValue ? $this->resolveAppendableAttributeDefault($attributeDefaults, $key, $escape) : ($attributeDefaults[$key] ?? '');
return [$key => implode(' ', array_unique(array_filter([$defaultsValue, $value])))]; })->merge($nonAppendableAttributes)->all();
return new static(array_merge($attributeDefaults, $attributes)); }
/** * Determine if the specific attribute value should be escaped. * * @param bool $escape * @param mixed $value * @return bool */ protected function shouldEscapeAttributeValue($escape, $value) { if (! $escape) { return false; }
return ! is_object($value) && ! is_null($value) && ! is_bool($value); }
/** * Create a new appendable attribute value. * * @param mixed $value * @return \Illuminate\View\AppendableAttributeValue */ public function prepends($value) { return new AppendableAttributeValue($value); }
/** * Resolve an appendable attribute value default value. * * @param array $attributeDefaults * @param string $key * @param bool $escape * @return mixed */ protected function resolveAppendableAttributeDefault($attributeDefaults, $key, $escape) { if ($this->shouldEscapeAttributeValue($escape, $value = $attributeDefaults[$key]->value)) { $value = e($value); }
return $value; }
/** * Get all of the raw attributes. * * @return array */ public function getAttributes() { return $this->attributes; }
/** * Set the underlying attributes. * * @param array $attributes * @return void */ public function setAttributes(array $attributes) { if (isset($attributes['attributes']) && $attributes['attributes'] instanceof self) { $parentBag = $attributes['attributes'];
unset($attributes['attributes']);
$attributes = $parentBag->merge($attributes, $escape = false)->getAttributes(); }
$this->attributes = $attributes; }
/** * Get content as a string of HTML. * * @return string */ public function toHtml() { return (string) $this; }
/** * Merge additional attributes / values into the attribute bag. * * @param array $attributeDefaults * @return \Illuminate\Support\HtmlString */ public function __invoke(array $attributeDefaults = []) { return new HtmlString((string) $this->merge($attributeDefaults)); }
/** * Determine if the given offset exists. * * @param string $offset * @return bool */ #[\ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->attributes[$offset]); }
/** * Get the value at the given offset. * * @param string $offset * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($offset) { return $this->get($offset); }
/** * Set the value at a given offset. * * @param string $offset * @param mixed $value * @return void */ #[\ReturnTypeWillChange] public function offsetSet($offset, $value) { $this->attributes[$offset] = $value; }
/** * Remove the value at the given offset. * * @param string $offset * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->attributes[$offset]); }
/** * Get an iterator for the items. * * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->attributes); }
/** * Implode the attributes into a single HTML ready string. * * @return string */ public function __toString() { $string = '';
foreach ($this->attributes as $key => $value) { if ($value === false || is_null($value)) { continue; }
if ($value === true) { $value = $key; }
$string .= ' '.$key.'="'.str_replace('"', '\\"', trim($value)).'"'; }
return trim($string); } }
|