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;
4
 
5
use Illuminate\Container\Container;
6
use Illuminate\Support\Str;
7
use Illuminate\View\Compilers\ComponentTagCompiler;
8
 
9
class DynamicComponent extends Component
10
{
11
    /**
12
     * The name of the component.
13
     *
14
     * @var string
15
     */
16
    public $component;
17
 
18
    /**
19
     * The component tag compiler instance.
20
     *
21
     * @var \Illuminate\View\Compilers\BladeTagCompiler
22
     */
23
    protected static $compiler;
24
 
25
    /**
26
     * The cached component classes.
27
     *
28
     * @var array
29
     */
30
    protected static $componentClasses = [];
31
 
32
    /**
33
     * Create a new component instance.
34
     *
35
     * @param  string  $component
36
     * @return void
37
     */
38
    public function __construct(string $component)
39
    {
40
        $this->component = $component;
41
    }
42
 
43
    /**
44
     * Get the view / contents that represent the component.
45
     *
46
     * @return \Illuminate\Contracts\View\View|string
47
     */
48
    public function render()
49
    {
50
        $template = <<<'EOF'
51
<?php extract(collect($attributes->getAttributes())->mapWithKeys(function ($value, $key) { return [Illuminate\Support\Str::camel(str_replace([':', '.'], ' ', $key)) => $value]; })->all(), EXTR_SKIP); ?>
52
{{ props }}
53
<x-{{ component }} {{ bindings }} {{ attributes }}>
54
{{ slots }}
55
{{ defaultSlot }}
56
</x-{{ component }}>
57
EOF;
58
 
59
        return function ($data) use ($template) {
60
            $bindings = $this->bindings($class = $this->classForComponent());
61
 
62
            return str_replace(
63
                [
64
                    '{{ component }}',
65
                    '{{ props }}',
66
                    '{{ bindings }}',
67
                    '{{ attributes }}',
68
                    '{{ slots }}',
69
                    '{{ defaultSlot }}',
70
                ],
71
                [
72
                    $this->component,
73
                    $this->compileProps($bindings),
74
                    $this->compileBindings($bindings),
75
                    class_exists($class) ? '{{ $attributes }}' : '',
76
                    $this->compileSlots($data['__laravel_slots']),
77
                    '{{ $slot ?? "" }}',
78
                ],
79
                $template
80
            );
81
        };
82
    }
83
 
84
    /**
85
     * Compile the @props directive for the component.
86
     *
87
     * @param  array  $bindings
88
     * @return string
89
     */
90
    protected function compileProps(array $bindings)
91
    {
92
        if (empty($bindings)) {
93
            return '';
94
        }
95
 
96
        return '@props('.'[\''.implode('\',\'', collect($bindings)->map(function ($dataKey) {
97
            return Str::camel($dataKey);
98
        })->all()).'\']'.')';
99
    }
100
 
101
    /**
102
     * Compile the bindings for the component.
103
     *
104
     * @param  array  $bindings
105
     * @return string
106
     */
107
    protected function compileBindings(array $bindings)
108
    {
109
        return collect($bindings)->map(function ($key) {
110
            return ':'.$key.'="$'.Str::camel(str_replace([':', '.'], ' ', $key)).'"';
111
        })->implode(' ');
112
    }
113
 
114
    /**
115
     * Compile the slots for the component.
116
     *
117
     * @param  array  $slots
118
     * @return string
119
     */
120
    protected function compileSlots(array $slots)
121
    {
122
        return collect($slots)->map(function ($slot, $name) {
123
            return $name === '__default' ? null : '<x-slot name="'.$name.'" '.((string) $slot->attributes).'>{{ $'.$name.' }}</x-slot>';
124
        })->filter()->implode(PHP_EOL);
125
    }
126
 
127
    /**
128
     * Get the class for the current component.
129
     *
130
     * @return string
131
     */
132
    protected function classForComponent()
133
    {
134
        if (isset(static::$componentClasses[$this->component])) {
135
            return static::$componentClasses[$this->component];
136
        }
137
 
138
        return static::$componentClasses[$this->component] =
139
                    $this->compiler()->componentClass($this->component);
140
    }
141
 
142
    /**
143
     * Get the names of the variables that should be bound to the component.
144
     *
145
     * @param  string  $class
146
     * @return array
147
     */
148
    protected function bindings(string $class)
149
    {
150
        [$data, $attributes] = $this->compiler()->partitionDataAndAttributes($class, $this->attributes->getAttributes());
151
 
152
        return array_keys($data->all());
153
    }
154
 
155
    /**
156
     * Get an instance of the Blade tag compiler.
157
     *
158
     * @return \Illuminate\View\Compilers\ComponentTagCompiler
159
     */
160
    protected function compiler()
161
    {
162
        if (! static::$compiler) {
163
            static::$compiler = new ComponentTagCompiler(
164
                Container::getInstance()->make('blade.compiler')->getClassComponentAliases(),
165
                Container::getInstance()->make('blade.compiler')->getClassComponentNamespaces(),
166
                Container::getInstance()->make('blade.compiler')
167
            );
168
        }
169
 
170
        return static::$compiler;
171
    }
172
}