Passed
Push — master ( ee41eb...972703 )
by Bruno
03:32
created

FrontendVueGenerator::buildTemplateParameters()   B

Complexity

Conditions 7
Paths 2

Size

Total Lines 54
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 43
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 54
rs 8.2986

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        $this->buildTemplateParameters();
31
    }
32
33
    protected function getCollection(): GeneratedCollection
34
    {
35
        return $this->generator->getCollection();
36
    }
37
38
    public function generate(): void
39
    {
40
        /**
41
         * @var FrameworkVue $vue
42
         */
43
        $vue = $this->generator->getComposer()->getByName('Vue');
44
        $vueCode = $vue->getVueCode();
45
46
        // set basic data for vue
47
        $extraprops = [
48
            [
49
                'name' => 'id',
50
                'type' => 'String',
51
                'required' => true
52
            ]
53
        ];
54
        $vueCode->setExtraProps($extraprops);
55
56
        // build basic vue components
57
        $this->vuePublish();
58
        $this->makeVuePaginationComponent();
59
60
        $this->vueCard($vue);
61
        $this->vueLink($vue);
62
        $this->vueTableItem($vue);
63
        $this->vueTable($vue);
64
65
        $this->makeVue($vue, 'List', 'viewable');
66
        $this->makeVue($vue, 'Show', 'viewable');
67
        $this->makeVue($vue, 'Edit', 'editable');
68
        $this->makeVue(
69
            $vue,
70
            'Form',
71
            'editable',
72
            function (Field $f) {
73
                if (!$f->getExtradata('modelFillable')) {
74
                    return false;
75
                }
76
                return true;
77
            }
78
        );
79
        $this->makeVueRoutes();
80
        $this->makeVueIndex();
81
    }
82
83
    public function buildTemplateParameters(): void
84
    {
85
        $hasVuex = true; // TODO
86
        $hasCan = $this->generator->getModel()->getExtradataValue('hasCan', 'value', false);
87
        $routeBase = $this->generator->getRouteBase();
88
        $keyAttribute = $this->generator->getKeyAttribute();
89
        $targetAttribute = $hasVuex ? 'to' : 'href';
0 ignored issues
show
introduced by
The condition $hasVuex is always true.
Loading history...
90
        $buttonCreate = $this->generator->getComposer()->nodeElement(
91
            'Button',
92
            [
93
                Button::TYPE => ($hasVuex ? 'router-link' : 'a'),
0 ignored issues
show
introduced by
The condition $hasVuex is always true.
Loading history...
94
                Button::ATTRIBUTES => [
95
                    $targetAttribute => "/{$routeBase}/edit",
96
                ] + ($hasCan ? [ "v-if" => 'can.create' ]: []),
97
            ]
98
        )->setContent(
99
            '<i class="fa fa-plus"></i> Add new',
100
            true,
101
            true
102
        )->getRenderHTML();
103
104
        $buttonEdit = $this->generator->getComposer()->nodeElement(
105
            'Button',
106
            [
107
                Button::TYPE => ($hasVuex ? 'router-link' : 'a'),
0 ignored issues
show
introduced by
The condition $hasVuex is always true.
Loading history...
108
                Button::ATTRIBUTES => [
109
                    $targetAttribute => "'/{$routeBase}/' + model.{$keyAttribute} + '/edit'",
110
                ] + ($hasCan ? [ "v-if" => 'can.edit' ]: []),
111
            ]
112
        )->setContent(
113
            '<i class="fa fa-pencil"></i> Edit',
114
            true,
115
            true
116
        )->getRenderHTML();
117
118
        $buttonDelete = $this->generator->getComposer()->nodeElement(
119
            'Button',
120
            [
121
                Button::TYPE => 'a',
122
                Button::COLOR => Button::COLOR_WARNING,
123
                Button::ATTRIBUTES => [
124
                    'href' => '#',
125
                    '@click.prevent' => 'remove',
126
                ] + ($hasCan ? [ "v-if" => 'can.delete' ]: []),
127
            ]
128
        )->setContent(
129
            '<i class="fa fa-trash"></i> Delete',
130
            true,
131
            true
132
        )->getRenderHTML();
133
134
        $this->generator->templateParameters['buttonCreate'] = $buttonCreate;
135
        $this->generator->templateParameters['buttonEdit'] = $buttonEdit;
136
        $this->generator->templateParameters['buttonDelete'] = $buttonDelete;
137
    }
138
139
    /**
140
     * Publishes the Vue component dependencies
141
     *
142
     * @return void
143
     */
144
    protected function vuePublish(): void
145
    {
146
        $this->getCollection()->push(
147
            new GeneratedItem(
148
                GeneratedItem::TYPE_FRONTEND,
149
                file_get_contents(__DIR__ . "/Vue/Renderable/RelationshipAutocomplete.vue"),
150
                "Modelarium/RelationshipAutocomplete.vue"
151
            )
152
        );
153
        $this->getCollection()->push(
154
            new GeneratedItem(
155
                GeneratedItem::TYPE_FRONTEND,
156
                file_get_contents(__DIR__ . "/Vue/Renderable/RelationshipSelect.vue"),
157
                "Modelarium/RelationshipSelect.vue"
158
            )
159
        );
160
        // $this->getCollection()->push(
161
        //     new GeneratedItem(
162
        //         GeneratedItem::TYPE_FRONTEND,
163
        //         file_get_contents(__DIR__ . "/Vue/Renderable/RelationshipSelectMultiple.vue"),
164
        //         "Modelarium/RelationshipSelectMultiple.vue"
165
        //     )
166
        // );
167
    }
168
169
    protected function makeVuePaginationComponent(): void
170
    {
171
        // TODO: this is called once per type
172
        $pagination = $this->generator->getComposer()->nodeElement(
173
            'Pagination',
174
            [
175
            ]
176
        );
177
        $html = $pagination->getRenderHTML();
178
        $script = PaginationVue::script();
179
180
        $this->getCollection()->push(
181
            new GeneratedItem(
182
                GeneratedItem::TYPE_FRONTEND,
183
                "<template>\n$html\n</template>\n<script>\n$script\n</script>\n",
184
                "Modelarium/Pagination.vue"
185
            )
186
        );
187
    }
188
189
    /**
190
     * Appends computed item
191
     *
192
     * @param FrameworkVue $vue
193
     * @return void
194
     */
195
    protected function vueCodeLinkItem(FrameworkVue $vue): void
196
    {
197
        $vue->getVueCode()->appendComputed(
198
            'link',
199
            'return "/' . $this->generator->getRouteBase() .
200
                '/" + this.' . $this->generator->getKeyAttribute()
201
        );
202
    }
203
204
    protected function vueCard(FrameworkVue $vue): void
205
    {
206
        $vueCode = $vue->getVueCode();
207
        // set basic data for vue
208
        $extraprops = [
209
            [
210
                'name' => 'id',
211
                'type' => 'String',
212
                'required' => true
213
            ]
214
        ];
215
        $cardFieldNames = array_map(function (Field $f) {
216
            return $f->getName();
217
        }, $this->generator->getCardFields());
218
        $vueCode->setExtraProps($extraprops);
219
        $this->vueCodeLinkItem($vue);
220
221
        foreach ($this->generator->getCardFields() as $f) {
222
            $vueCode->appendExtraProp([
223
                'name' => $f->getName(),
224
                'type' => $vueCode->mapTypeToJs($f->getDatatype()),
225
                'required' => true
226
            ]);
227
        }
228
        $this->makeVue($vue, 'Card', 'viewable', $cardFieldNames);
229
    }
230
231
    protected function vueLink(FrameworkVue $vue): void
232
    {
233
        $vueCode = $vue->getVueCode();
234
        // set basic data for vue
235
        $extraprops = [
236
            [
237
                'name' => 'id',
238
                'type' => 'String',
239
                'required' => true
240
            ]
241
        ];
242
        $vueCode->setExtraProps($extraprops);
243
        $cardFieldNames = array_map(function (Field $f) {
244
            return $f->getName();
245
        }, $this->generator->getCardFields());
246
        foreach ($this->generator->getCardFields() as $f) {
247
            $vueCode->appendExtraProp([
248
                'name' => $f->getName(),
249
                'type' => $vueCode->mapTypeToJs($f->getDatatype()),
250
                'required' => true
251
            ]);
252
        }
253
        $this->vueCodeLinkItem($vue);
254
        $this->makeVue($vue, 'Link', 'viewable', $cardFieldNames);
255
    }
256
257
    public function vueTableItem(FrameworkVue $vue): void
258
    {
259
        $vueCode = $vue->getVueCode();
260
        $tableFieldNames = array_map(function (Field $f) {
261
            return $f->getName();
262
        }, $this->generator->getTableFields());
263
        $extraprops = [
264
            [
265
                'name' => 'id',
266
                'type' => 'String',
267
                'required' => true
268
            ]
269
        ];
270
        $vueCode->setExtraProps($extraprops);
271
        foreach ($this->generator->getTableFields() as $f) {
272
            $vueCode->appendExtraProp([
273
                'name' => $f->getName(),
274
                'type' => $vueCode->mapTypeToJs($f->getDatatype()),
275
                'required' => true
276
            ]);
277
        }
278
        $this->makeVue($vue, 'TableItem', 'viewable', $tableFieldNames);
279
    }
280
281
    public function vueTable(FrameworkVue $vue): void
282
    {
283
        $this->makeVue($vue, 'Table', 'viewable');
284
    }
285
286
    /**
287
     * @param FrameworkVue $vue
288
     * @param string $component
289
     * @param string $mode
290
     * @param string[]|callable $restrictFields
291
     * @return void
292
     */
293
    protected function makeVue(FrameworkVue $vue, string $component, string $mode, $restrictFields = null): void
294
    {
295
        $path = $this->generator->getModel()->getName() . '/' .
296
            $this->generator->getModel()->getName() . $component . '.vue';
297
298
        $stub = $this->generator->getStubDir() . "/Vue{$component}.mustache.vue";
299
300
        if ($mode == 'editable') {
301
            $vue->setEditableTemplate(
302
                function (FrameworkVue $vue, array $data, Model $m) use ($stub) {
303
                    return $this->generator->templateCallback($stub, $vue, $data, $m);
304
                }
305
            );
306
307
            $this->getCollection()->push(
308
                new GeneratedItem(
309
                    GeneratedItem::TYPE_FRONTEND,
310
                    $this->generator->getModel()->editable($this->generator->getComposer(), [], $restrictFields),
311
                    $path
312
                )
313
            );
314
        } else {
315
            $vue->setViewableTemplate(
316
                function (FrameworkVue $vue, array $data, Model $m) use ($stub) {
317
                    return $this->generator->templateCallback($stub, $vue, $data, $m);
318
                }
319
            );
320
321
            $this->getCollection()->push(
322
                new GeneratedItem(
323
                    GeneratedItem::TYPE_FRONTEND,
324
                    $this->generator->getModel()->viewable($this->generator->getComposer(), [], $restrictFields),
325
                    $path
326
                )
327
            );
328
        }
329
        $vue->resetVueCode();
330
        $vue->getVueCode()->setFieldModelVariable('model.');
331
    }
332
333
    protected function makeVueIndex(): void
334
    {
335
        $path = $this->generator->getModel()->getName() . '/index.js';
336
        $name = $this->generator->getStudlyName();
337
338
        $items = [
339
            'Card',
340
            'Edit',
341
            'Link',
342
            'List',
343
            'Show',
344
            'Table',
345
        ];
346
347
        $import = array_map(
348
            function ($i) use ($name) {
349
                return "import {$name}$i from './{$name}$i.vue';";
350
            },
351
            $items
352
        );
353
354
        $export = array_map(
355
            function ($i) use ($name) {
356
                return "    {$name}$i,\n";
357
            },
358
            $items
359
        );
360
361
        $this->getCollection()->push(
362
            new GeneratedItem(
363
                GeneratedItem::TYPE_FRONTEND,
364
                implode("\n", $import) . "\n" .
365
                "export {\n" .
366
                implode("\n", $export) . "\n};\n",
367
                $path
368
            )
369
        );
370
    }
371
372
    protected function makeVueRoutes(): void
373
    {
374
        $path = $this->generator->getModel()->getName() . '/routes.js';
375
376
        $this->getCollection()->push(
377
            new GeneratedItem(
378
                GeneratedItem::TYPE_FRONTEND,
379
                $this->generator->templateFile(
380
                    $this->generator->getStubDir() . "/routes.mustache.js",
381
                    [
382
                        'routeName' => $this->generator->getRouteBase(),
383
                        'keyAttribute' => $this->generator->getKeyAttribute()
384
                    ]
385
                ),
386
                $path
387
            )
388
        );
389
    }
390
}
391