Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\View\Concerns;
4
 
5
use Illuminate\Contracts\Support\Htmlable;
6
use Illuminate\Contracts\View\View;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\HtmlString;
9
use Illuminate\View\ComponentSlot;
10
 
11
trait ManagesComponents
12
{
13
    /**
14
     * The components being rendered.
15
     *
16
     * @var array
17
     */
18
    protected $componentStack = [];
19
 
20
    /**
21
     * The original data passed to the component.
22
     *
23
     * @var array
24
     */
25
    protected $componentData = [];
26
 
27
    /**
28
     * The component data for the component that is currently being rendered.
29
     *
30
     * @var array
31
     */
32
    protected $currentComponentData = [];
33
 
34
    /**
35
     * The slot contents for the component.
36
     *
37
     * @var array
38
     */
39
    protected $slots = [];
40
 
41
    /**
42
     * The names of the slots being rendered.
43
     *
44
     * @var array
45
     */
46
    protected $slotStack = [];
47
 
48
    /**
49
     * Start a component rendering process.
50
     *
51
     * @param  \Illuminate\Contracts\View\View|\Illuminate\Contracts\Support\Htmlable|\Closure|string  $view
52
     * @param  array  $data
53
     * @return void
54
     */
55
    public function startComponent($view, array $data = [])
56
    {
57
        if (ob_start()) {
58
            $this->componentStack[] = $view;
59
 
60
            $this->componentData[$this->currentComponent()] = $data;
61
 
62
            $this->slots[$this->currentComponent()] = [];
63
        }
64
    }
65
 
66
    /**
67
     * Get the first view that actually exists from the given list, and start a component.
68
     *
69
     * @param  array  $names
70
     * @param  array  $data
71
     * @return void
72
     */
73
    public function startComponentFirst(array $names, array $data = [])
74
    {
75
        $name = Arr::first($names, function ($item) {
76
            return $this->exists($item);
77
        });
78
 
79
        $this->startComponent($name, $data);
80
    }
81
 
82
    /**
83
     * Render the current component.
84
     *
85
     * @return string
86
     */
87
    public function renderComponent()
88
    {
89
        $view = array_pop($this->componentStack);
90
 
91
        $this->currentComponentData = array_merge(
92
            $previousComponentData = $this->currentComponentData,
93
            $data = $this->componentData()
94
        );
95
 
96
        try {
97
            $view = value($view, $data);
98
 
99
            if ($view instanceof View) {
100
                return $view->with($data)->render();
101
            } elseif ($view instanceof Htmlable) {
102
                return $view->toHtml();
103
            } else {
104
                return $this->make($view, $data)->render();
105
            }
106
        } finally {
107
            $this->currentComponentData = $previousComponentData;
108
        }
109
    }
110
 
111
    /**
112
     * Get the data for the given component.
113
     *
114
     * @return array
115
     */
116
    protected function componentData()
117
    {
118
        $defaultSlot = new HtmlString(trim(ob_get_clean()));
119
 
120
        $slots = array_merge([
121
            '__default' => $defaultSlot,
122
        ], $this->slots[count($this->componentStack)]);
123
 
124
        return array_merge(
125
            $this->componentData[count($this->componentStack)],
126
            ['slot' => $defaultSlot],
127
            $this->slots[count($this->componentStack)],
128
            ['__laravel_slots' => $slots]
129
        );
130
    }
131
 
132
    /**
133
     * Get an item from the component data that exists above the current component.
134
     *
135
     * @param  string  $key
136
     * @param  mixed  $default
137
     * @return mixed|null
138
     */
139
    public function getConsumableComponentData($key, $default = null)
140
    {
141
        if (array_key_exists($key, $this->currentComponentData)) {
142
            return $this->currentComponentData[$key];
143
        }
144
 
145
        $currentComponent = count($this->componentStack);
146
 
147
        if ($currentComponent === 0) {
148
            return value($default);
149
        }
150
 
151
        for ($i = $currentComponent - 1; $i >= 0; $i--) {
152
            $data = $this->componentData[$i] ?? [];
153
 
154
            if (array_key_exists($key, $data)) {
155
                return $data[$key];
156
            }
157
        }
158
 
159
        return value($default);
160
    }
161
 
162
    /**
163
     * Start the slot rendering process.
164
     *
165
     * @param  string  $name
166
     * @param  string|null  $content
167
     * @param  array  $attributes
168
     * @return void
169
     */
170
    public function slot($name, $content = null, $attributes = [])
171
    {
172
        if (func_num_args() === 2 || $content !== null) {
173
            $this->slots[$this->currentComponent()][$name] = $content;
174
        } elseif (ob_start()) {
175
            $this->slots[$this->currentComponent()][$name] = '';
176
 
177
            $this->slotStack[$this->currentComponent()][] = [$name, $attributes];
178
        }
179
    }
180
 
181
    /**
182
     * Save the slot content for rendering.
183
     *
184
     * @return void
185
     */
186
    public function endSlot()
187
    {
188
        last($this->componentStack);
189
 
190
        $currentSlot = array_pop(
191
            $this->slotStack[$this->currentComponent()]
192
        );
193
 
194
        [$currentName, $currentAttributes] = $currentSlot;
195
 
196
        $this->slots[$this->currentComponent()][$currentName] = new ComponentSlot(
197
            trim(ob_get_clean()), $currentAttributes
198
        );
199
    }
200
 
201
    /**
202
     * Get the index for the current component.
203
     *
204
     * @return int
205
     */
206
    protected function currentComponent()
207
    {
208
        return count($this->componentStack) - 1;
209
    }
210
 
211
    /**
212
     * Flush all of the component state.
213
     *
214
     * @return void
215
     */
216
    protected function flushComponents()
217
    {
218
        $this->componentStack = [];
219
        $this->componentData = [];
220
        $this->currentComponentData = [];
221
    }
222
}