Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\View;
4
 
5
use ArrayAccess;
6
use ArrayIterator;
7
use Illuminate\Contracts\Support\Htmlable;
8
use Illuminate\Support\Arr;
9
use Illuminate\Support\HtmlString;
10
use Illuminate\Support\Str;
11
use Illuminate\Support\Traits\Conditionable;
12
use Illuminate\Support\Traits\Macroable;
13
use IteratorAggregate;
14
use Traversable;
15
 
16
class ComponentAttributeBag implements ArrayAccess, Htmlable, IteratorAggregate
17
{
18
    use Conditionable, Macroable;
19
 
20
    /**
21
     * The raw array of attributes.
22
     *
23
     * @var array
24
     */
25
    protected $attributes = [];
26
 
27
    /**
28
     * Create a new component attribute bag instance.
29
     *
30
     * @param  array  $attributes
31
     * @return void
32
     */
33
    public function __construct(array $attributes = [])
34
    {
35
        $this->attributes = $attributes;
36
    }
37
 
38
    /**
39
     * Get the first attribute's value.
40
     *
41
     * @param  mixed  $default
42
     * @return mixed
43
     */
44
    public function first($default = null)
45
    {
46
        return $this->getIterator()->current() ?? value($default);
47
    }
48
 
49
    /**
50
     * Get a given attribute from the attribute array.
51
     *
52
     * @param  string  $key
53
     * @param  mixed  $default
54
     * @return mixed
55
     */
56
    public function get($key, $default = null)
57
    {
58
        return $this->attributes[$key] ?? value($default);
59
    }
60
 
61
    /**
62
     * Determine if a given attribute exists in the attribute array.
63
     *
64
     * @param  string  $key
65
     * @return bool
66
     */
67
    public function has($key)
68
    {
69
        return array_key_exists($key, $this->attributes);
70
    }
71
 
72
    /**
73
     * Determine if a given attribute is missing from the attribute array.
74
     *
75
     * @param  string  $key
76
     * @return bool
77
     */
78
    public function missing($key)
79
    {
80
        return ! $this->has($key, $this->attributes);
81
    }
82
 
83
    /**
84
     * Only include the given attribute from the attribute array.
85
     *
86
     * @param  mixed  $keys
87
     * @return static
88
     */
89
    public function only($keys)
90
    {
91
        if (is_null($keys)) {
92
            $values = $this->attributes;
93
        } else {
94
            $keys = Arr::wrap($keys);
95
 
96
            $values = Arr::only($this->attributes, $keys);
97
        }
98
 
99
        return new static($values);
100
    }
101
 
102
    /**
103
     * Exclude the given attribute from the attribute array.
104
     *
105
     * @param  mixed|array  $keys
106
     * @return static
107
     */
108
    public function except($keys)
109
    {
110
        if (is_null($keys)) {
111
            $values = $this->attributes;
112
        } else {
113
            $keys = Arr::wrap($keys);
114
 
115
            $values = Arr::except($this->attributes, $keys);
116
        }
117
 
118
        return new static($values);
119
    }
120
 
121
    /**
122
     * Filter the attributes, returning a bag of attributes that pass the filter.
123
     *
124
     * @param  callable  $callback
125
     * @return static
126
     */
127
    public function filter($callback)
128
    {
129
        return new static(collect($this->attributes)->filter($callback)->all());
130
    }
131
 
132
    /**
133
     * Return a bag of attributes that have keys starting with the given value / pattern.
134
     *
135
     * @param  string|string[]  $needles
136
     * @return static
137
     */
138
    public function whereStartsWith($needles)
139
    {
140
        return $this->filter(function ($value, $key) use ($needles) {
141
            return Str::startsWith($key, $needles);
142
        });
143
    }
144
 
145
    /**
146
     * Return a bag of attributes with keys that do not start with the given value / pattern.
147
     *
148
     * @param  string|string[]  $needles
149
     * @return static
150
     */
151
    public function whereDoesntStartWith($needles)
152
    {
153
        return $this->filter(function ($value, $key) use ($needles) {
154
            return ! Str::startsWith($key, $needles);
155
        });
156
    }
157
 
158
    /**
159
     * Return a bag of attributes that have keys starting with the given value / pattern.
160
     *
161
     * @param  string|string[]  $needles
162
     * @return static
163
     */
164
    public function thatStartWith($needles)
165
    {
166
        return $this->whereStartsWith($needles);
167
    }
168
 
169
    /**
170
     * Only include the given attribute from the attribute array.
171
     *
172
     * @param  mixed|array  $keys
173
     * @return static
174
     */
175
    public function onlyProps($keys)
176
    {
177
        return $this->only($this->extractPropNames($keys));
178
    }
179
 
180
    /**
181
     * Exclude the given attribute from the attribute array.
182
     *
183
     * @param  mixed|array  $keys
184
     * @return static
185
     */
186
    public function exceptProps($keys)
187
    {
188
        return $this->except($this->extractPropNames($keys));
189
    }
190
 
191
    /**
192
     * Extract prop names from given keys.
193
     *
194
     * @param  mixed|array  $keys
195
     * @return array
196
     */
197
    protected function extractPropNames($keys)
198
    {
199
        $props = [];
200
 
201
        foreach ($keys as $key => $defaultValue) {
202
            $key = is_numeric($key) ? $defaultValue : $key;
203
 
204
            $props[] = $key;
205
            $props[] = Str::kebab($key);
206
        }
207
 
208
        return $props;
209
    }
210
 
211
    /**
212
     * Conditionally merge classes into the attribute bag.
213
     *
214
     * @param  mixed|array  $classList
215
     * @return static
216
     */
217
    public function class($classList)
218
    {
219
        $classList = Arr::wrap($classList);
220
 
221
        return $this->merge(['class' => Arr::toCssClasses($classList)]);
222
    }
223
 
224
    /**
225
     * Merge additional attributes / values into the attribute bag.
226
     *
227
     * @param  array  $attributeDefaults
228
     * @param  bool  $escape
229
     * @return static
230
     */
231
    public function merge(array $attributeDefaults = [], $escape = true)
232
    {
233
        $attributeDefaults = array_map(function ($value) use ($escape) {
234
            return $this->shouldEscapeAttributeValue($escape, $value)
235
                        ? e($value)
236
                        : $value;
237
        }, $attributeDefaults);
238
 
239
        [$appendableAttributes, $nonAppendableAttributes] = collect($this->attributes)
240
                    ->partition(function ($value, $key) use ($attributeDefaults) {
241
                        return $key === 'class' ||
242
                               (isset($attributeDefaults[$key]) &&
243
                                $attributeDefaults[$key] instanceof AppendableAttributeValue);
244
                    });
245
 
246
        $attributes = $appendableAttributes->mapWithKeys(function ($value, $key) use ($attributeDefaults, $escape) {
247
            $defaultsValue = isset($attributeDefaults[$key]) && $attributeDefaults[$key] instanceof AppendableAttributeValue
248
                        ? $this->resolveAppendableAttributeDefault($attributeDefaults, $key, $escape)
249
                        : ($attributeDefaults[$key] ?? '');
250
 
251
            return [$key => implode(' ', array_unique(array_filter([$defaultsValue, $value])))];
252
        })->merge($nonAppendableAttributes)->all();
253
 
254
        return new static(array_merge($attributeDefaults, $attributes));
255
    }
256
 
257
    /**
258
     * Determine if the specific attribute value should be escaped.
259
     *
260
     * @param  bool  $escape
261
     * @param  mixed  $value
262
     * @return bool
263
     */
264
    protected function shouldEscapeAttributeValue($escape, $value)
265
    {
266
        if (! $escape) {
267
            return false;
268
        }
269
 
270
        return ! is_object($value) &&
271
               ! is_null($value) &&
272
               ! is_bool($value);
273
    }
274
 
275
    /**
276
     * Create a new appendable attribute value.
277
     *
278
     * @param  mixed  $value
279
     * @return \Illuminate\View\AppendableAttributeValue
280
     */
281
    public function prepends($value)
282
    {
283
        return new AppendableAttributeValue($value);
284
    }
285
 
286
    /**
287
     * Resolve an appendable attribute value default value.
288
     *
289
     * @param  array  $attributeDefaults
290
     * @param  string  $key
291
     * @param  bool  $escape
292
     * @return mixed
293
     */
294
    protected function resolveAppendableAttributeDefault($attributeDefaults, $key, $escape)
295
    {
296
        if ($this->shouldEscapeAttributeValue($escape, $value = $attributeDefaults[$key]->value)) {
297
            $value = e($value);
298
        }
299
 
300
        return $value;
301
    }
302
 
303
    /**
304
     * Get all of the raw attributes.
305
     *
306
     * @return array
307
     */
308
    public function getAttributes()
309
    {
310
        return $this->attributes;
311
    }
312
 
313
    /**
314
     * Set the underlying attributes.
315
     *
316
     * @param  array  $attributes
317
     * @return void
318
     */
319
    public function setAttributes(array $attributes)
320
    {
321
        if (isset($attributes['attributes']) &&
322
            $attributes['attributes'] instanceof self) {
323
            $parentBag = $attributes['attributes'];
324
 
325
            unset($attributes['attributes']);
326
 
327
            $attributes = $parentBag->merge($attributes, $escape = false)->getAttributes();
328
        }
329
 
330
        $this->attributes = $attributes;
331
    }
332
 
333
    /**
334
     * Get content as a string of HTML.
335
     *
336
     * @return string
337
     */
338
    public function toHtml()
339
    {
340
        return (string) $this;
341
    }
342
 
343
    /**
344
     * Merge additional attributes / values into the attribute bag.
345
     *
346
     * @param  array  $attributeDefaults
347
     * @return \Illuminate\Support\HtmlString
348
     */
349
    public function __invoke(array $attributeDefaults = [])
350
    {
351
        return new HtmlString((string) $this->merge($attributeDefaults));
352
    }
353
 
354
    /**
355
     * Determine if the given offset exists.
356
     *
357
     * @param  string  $offset
358
     * @return bool
359
     */
360
    public function offsetExists($offset): bool
361
    {
362
        return isset($this->attributes[$offset]);
363
    }
364
 
365
    /**
366
     * Get the value at the given offset.
367
     *
368
     * @param  string  $offset
369
     * @return mixed
370
     */
371
    public function offsetGet($offset): mixed
372
    {
373
        return $this->get($offset);
374
    }
375
 
376
    /**
377
     * Set the value at a given offset.
378
     *
379
     * @param  string  $offset
380
     * @param  mixed  $value
381
     * @return void
382
     */
383
    public function offsetSet($offset, $value): void
384
    {
385
        $this->attributes[$offset] = $value;
386
    }
387
 
388
    /**
389
     * Remove the value at the given offset.
390
     *
391
     * @param  string  $offset
392
     * @return void
393
     */
394
    public function offsetUnset($offset): void
395
    {
396
        unset($this->attributes[$offset]);
397
    }
398
 
399
    /**
400
     * Get an iterator for the items.
401
     *
402
     * @return \ArrayIterator
403
     */
404
    public function getIterator(): Traversable
405
    {
406
        return new ArrayIterator($this->attributes);
407
    }
408
 
409
    /**
410
     * Implode the attributes into a single HTML ready string.
411
     *
412
     * @return string
413
     */
414
    public function __toString()
415
    {
416
        $string = '';
417
 
418
        foreach ($this->attributes as $key => $value) {
419
            if ($value === false || is_null($value)) {
420
                continue;
421
            }
422
 
423
            if ($value === true) {
424
                $value = $key;
425
            }
426
 
427
            $string .= ' '.$key.'="'.str_replace('"', '\\"', trim($value)).'"';
428
        }
429
 
430
        return trim($string);
431
    }
432
}