Revision 148 | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace 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;use Traversable;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);}/*** Determine if a given attribute is missing from the attribute array.** @param string $key* @return bool*/public function missing($key){return ! $this->has($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);}/*** Only include the given attribute from the attribute array.** @param mixed|array $keys* @return static*/public function onlyProps($keys){return $this->only($this->extractPropNames($keys));}/*** Exclude the given attribute from the attribute array.** @param mixed|array $keys* @return static*/public function exceptProps($keys){return $this->except($this->extractPropNames($keys));}/*** Extract prop names from given keys.** @param mixed|array $keys* @return array*/protected function extractPropNames($keys){$props = [];foreach ($keys as $key => $defaultValue) {$key = is_numeric($key) ? $defaultValue : $key;$props[] = $key;$props[] = Str::kebab($key);}return $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)]);}/*** Conditionally merge styles into the attribute bag.** @param mixed|array $styleList* @return static*/public function style($styleList){$styleList = Arr::wrap($styleList);return $this->merge(['style' => Arr::toCssStyles($styleList)]);}/*** 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' || $key === 'style' || (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] ?? '');if ($key === 'style') {$value = Str::finish($value, ';');}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*/public function offsetExists($offset): bool{return isset($this->attributes[$offset]);}/*** Get the value at the given offset.** @param string $offset* @return mixed*/public function offsetGet($offset): mixed{return $this->get($offset);}/*** Set the value at a given offset.** @param string $offset* @param mixed $value* @return void*/public function offsetSet($offset, $value): void{$this->attributes[$offset] = $value;}/*** Remove the value at the given offset.** @param string $offset* @return void*/public function offsetUnset($offset): void{unset($this->attributes[$offset]);}/*** Get an iterator for the items.** @return \ArrayIterator*/public function getIterator(): Traversable{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);}}