Passed
Push — master ( 05064d...ef0947 )
by Bruno
04:00
created

FrontendVueGenerator::vuePublish()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 10
nc 1
nop 0
dl 0
loc 14
rs 9.9332
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Modelarium\Frontend;
4
5
use Formularium\Datatype;
6
use Formularium\Element;
7
use Formularium\Field;
8
use Formularium\Model;
9
use Formularium\FrameworkComposer;
10
use Formularium\Frontend\HTML\Element\Button;
11
use Formularium\Frontend\HTML\Element\Table;
12
use Formularium\Frontend\Vue\Element\Pagination as PaginationVue;
13
use Formularium\Frontend\Vue\Framework as FrameworkVue;
14
use Modelarium\GeneratedCollection;
15
use Modelarium\GeneratedItem;
16
17
use function Safe\file_get_contents;
18
use function Safe\json_encode;
19
20
class FrontendVueGenerator
21
{
22
    /**
23
     * @var FrontendGenerator
24
     */
25
    protected $generator = null;
26
27
    public function __construct(FrontendGenerator $generator)
28
    {
29
        $this->generator = $generator;
30
    }
31
32
    protected function getCollection(): GeneratedCollection
33
    {
34
        return $this->generator->getCollection();
35
    }
36
37
    public function generate(): void
38
    {
39
        /**
40
         * @var FrameworkVue $vue
41
         */
42
        $vue = $this->generator->getComposer()->getByName('Vue');
43
        $vueCode = $vue->getVueCode();
44
45
        // set basic data for vue
46
        $extraprops = [
47
            [
48
                'name' => 'id',
49
                'type' => 'String',
50
                'required' => true
51
            ]
52
        ];
53
        $vueCode->setExtraProps($extraprops);
54
55
        // build basic vue components
56
        $this->vuePublish();
57
        $this->makeVuePaginationComponent();
58
59
        $this->vueCard($vue);
60
        $this->vueLink($vue);
61
        $this->vueTableItem($vue);
62
        $this->vueTable($vue);
63
64
        $this->makeVue($vue, 'List', 'viewable');
65
        $this->makeVue($vue, 'Show', 'viewable');
66
        $this->makeVue($vue, 'Edit', 'editable');
67
        $this->makeVue(
68
            $vue,
69
            'Form',
70
            'editable',
71
            function (Field $f) {
72
                if (!$f->getExtradata('modelFillable')) {
73
                    return false;
74
                }
75
                return true;
76
            }
77
        );
78
        $this->makeVueRoutes();
79
        $this->makeVueIndex();
80
    }
81
82
    /**
83
     * Publishes the Vue component dependencies
84
     *
85
     * @return void
86
     */
87
    protected function vuePublish(): void
88
    {
89
        $this->getCollection()->push(
90
            new GeneratedItem(
91
                GeneratedItem::TYPE_FRONTEND,
92
                file_get_contents(__DIR__ . "/Vue/Renderable/RelationshipAutocomplete.vue"),
93
                "Modelarium/RelationshipAutocomplete.vue"
94
            )
95
        );
96
        $this->getCollection()->push(
97
            new GeneratedItem(
98
                GeneratedItem::TYPE_FRONTEND,
99
                file_get_contents(__DIR__ . "/Vue/Renderable/RelationshipSelect.vue"),
100
                "Modelarium/RelationshipSelect.vue"
101
            )
102
        );
103
        // $this->getCollection()->push(
104
        //     new GeneratedItem(
105
        //         GeneratedItem::TYPE_FRONTEND,
106
        //         file_get_contents(__DIR__ . "/Vue/Renderable/RelationshipSelectMultiple.vue"),
107
        //         "Modelarium/RelationshipSelectMultiple.vue"
108
        //     )
109
        // );
110
    }
111
112
    protected function makeVuePaginationComponent(): void
113
    {
114
        // TODO: this is called once per type
115
        $pagination = $this->generator->getComposer()->nodeElement(
116
            'Pagination',
117
            [
118
            ]
119
        );
120
        $html = $pagination->getRenderHTML();
121
        $script = PaginationVue::script();
122
123
        $this->getCollection()->push(
124
            new GeneratedItem(
125
                GeneratedItem::TYPE_FRONTEND,
126
                "<template>\n$html\n</template>\n<script>\n$script\n</script>\n",
127
                "Modelarium/Pagination.vue"
128
            )
129
        );
130
    }
131
132
    /**
133
     * Appends computed item
134
     *
135
     * @param FrameworkVue $vue
136
     * @return void
137
     */
138
    protected function vueCodeLinkItem(FrameworkVue $vue): void
139
    {
140
        $vue->getVueCode()->appendComputed(
141
            'link',
142
            'return "/' . $this->generator->getRouteBase() .
143
                '/" + this.' . $this->generator->getKeyAttribute()
144
        );
145
    }
146
147
    protected function vueCard(FrameworkVue $vue): void
148
    {
149
        $vueCode = $vue->getVueCode();
150
        // set basic data for vue
151
        $extraprops = [
152
            [
153
                'name' => 'id',
154
                'type' => 'String',
155
                'required' => true
156
            ]
157
        ];
158
        $cardFieldNames = array_map(function (Field $f) {
159
            return $f->getName();
160
        }, $this->generator->getCardFields());
161
        $vueCode->setExtraProps($extraprops);
162
        $this->vueCodeLinkItem($vue);
163
164
        foreach ($this->generator->getCardFields() as $f) {
165
            $vueCode->appendExtraProp([
166
                'name' => $f->getName(),
167
                'type' => $vueCode->mapTypeToJs($f->getDatatype()),
168
                'required' => true
169
            ]);
170
        }
171
        $this->makeVue($vue, 'Card', 'viewable', $cardFieldNames);
172
    }
173
174
    protected function vueLink(FrameworkVue $vue): void
175
    {
176
        $vueCode = $vue->getVueCode();
177
        // set basic data for vue
178
        $extraprops = [
179
            [
180
                'name' => 'id',
181
                'type' => 'String',
182
                'required' => true
183
            ]
184
        ];
185
        $vueCode->setExtraProps($extraprops);
186
        $cardFieldNames = array_map(function (Field $f) {
187
            return $f->getName();
188
        }, $this->generator->getCardFields());
189
        foreach ($this->generator->getCardFields() as $f) {
190
            $vueCode->appendExtraProp([
191
                'name' => $f->getName(),
192
                'type' => $vueCode->mapTypeToJs($f->getDatatype()),
193
                'required' => true
194
            ]);
195
        }
196
        $this->vueCodeLinkItem($vue);
197
        $this->makeVue($vue, 'Link', 'viewable', $cardFieldNames);
198
    }
199
200
    public function vueTableItem(FrameworkVue $vue): void
201
    {
202
        $vueCode = $vue->getVueCode();
203
        $tableFieldNames = array_map(function (Field $f) {
204
            return $f->getName();
205
        }, $this->generator->getTableFields());
206
        $extraprops = [
207
            [
208
                'name' => 'id',
209
                'type' => 'String',
210
                'required' => true
211
            ]
212
        ];
213
        $vueCode->setExtraProps($extraprops);
214
        foreach ($this->generator->getTableFields() as $f) {
215
            $vueCode->appendExtraProp([
216
                'name' => $f->getName(),
217
                'type' => $vueCode->mapTypeToJs($f->getDatatype()),
218
                'required' => true
219
            ]);
220
        }
221
        $this->makeVue($vue, 'TableItem', 'viewable', $tableFieldNames);
222
    }
223
224
    public function vueTable(FrameworkVue $vue): void
225
    {
226
        $this->makeVue($vue, 'Table', 'viewable');
227
    }
228
229
    /**
230
     * @param FrameworkVue $vue
231
     * @param string $component
232
     * @param string $mode
233
     * @param string[]|callable $restrictFields
234
     * @return void
235
     */
236
    protected function makeVue(FrameworkVue $vue, string $component, string $mode, $restrictFields = null): void
237
    {
238
        $path = $this->generator->getModel()->getName() . '/' .
239
            $this->generator->getModel()->getName() . $component . '.vue';
240
241
        $stub = $this->generator->getStubDir() . "/Vue{$component}.mustache.vue";
242
243
        if ($mode == 'editable') {
244
            $vue->setEditableTemplate(
245
                function (FrameworkVue $vue, array $data, Model $m) use ($stub) {
246
                    return $this->generator->templateCallback($stub, $vue, $data, $m);
247
                }
248
            );
249
250
            $this->getCollection()->push(
251
                new GeneratedItem(
252
                    GeneratedItem::TYPE_FRONTEND,
253
                    $this->generator->getModel()->editable($this->generator->getComposer(), [], $restrictFields),
254
                    $path
255
                )
256
            );
257
        } else {
258
            $vue->setViewableTemplate(
259
                function (FrameworkVue $vue, array $data, Model $m) use ($stub) {
260
                    return $this->generator->templateCallback($stub, $vue, $data, $m);
261
                }
262
            );
263
264
            $this->getCollection()->push(
265
                new GeneratedItem(
266
                    GeneratedItem::TYPE_FRONTEND,
267
                    $this->generator->getModel()->viewable($this->generator->getComposer(), [], $restrictFields),
268
                    $path
269
                )
270
            );
271
        }
272
        $vue->resetVueCode();
273
        $vue->getVueCode()->setFieldModelVariable('model.');
274
    }
275
276
    protected function makeVueIndex(): void
277
    {
278
        $path = $this->generator->getModel()->getName() . '/index.js';
279
        $name = $this->generator->getStudlyName();
280
281
        $items = [
282
            'Card',
283
            'Edit',
284
            'Link',
285
            'List',
286
            'Show',
287
            'Table',
288
        ];
289
290
        $import = array_map(
291
            function ($i) use ($name) {
292
                return "import {$name}$i from './{$name}$i.vue';";
293
            },
294
            $items
295
        );
296
297
        $export = array_map(
298
            function ($i) use ($name) {
299
                return "    {$name}$i,\n";
300
            },
301
            $items
302
        );
303
304
        $this->getCollection()->push(
305
            new GeneratedItem(
306
                GeneratedItem::TYPE_FRONTEND,
307
                implode("\n", $import) . "\n" .
308
                "export default {\n" .
309
                implode("\n", $export) . "\n};\n",
310
                $path
311
            )
312
        );
313
    }
314
315
    protected function makeVueRoutes(): void
316
    {
317
        $path = $this->generator->getModel()->getName() . '/routes.js';
318
319
        $this->getCollection()->push(
320
            new GeneratedItem(
321
                GeneratedItem::TYPE_FRONTEND,
322
                $this->generator->templateFile(
323
                    $this->generator->getStubDir() . "/routes.mustache.js",
324
                    [
325
                        'routeName' => $this->generator->getRouteBase(),
326
                        'keyAttribute' => $this->generator->getKeyAttribute()
327
                    ]
328
                ),
329
                $path
330
            )
331
        );
332
    }
333
}
334