Passed
Push — master ( bbba37...6fbfbb )
by Bruno
09:07
created

FrontendGenerator::makeJSModel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 11
rs 10
cc 1
nc 1
nop 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\Blade\Framework as FrameworkBlade;
11
use Formularium\Frontend\Vue\Framework as FrameworkVue;
12
use Modelarium\GeneratedCollection;
13
use Modelarium\GeneratedItem;
14
use Modelarium\GeneratorInterface;
15
use Modelarium\GeneratorNameTrait;
16
17
use function Safe\file_get_contents;
18
use function Safe\json_encode;
19
20
class FrontendGenerator implements GeneratorInterface
21
{
22
    use GeneratorNameTrait;
23
24
    /**
25
     * @var FrameworkComposer
26
     */
27
    protected $composer = null;
28
29
    /**
30
     * @var Model
31
     */
32
    protected $model = null;
33
34
    /**
35
     * @var GeneratedCollection
36
     */
37
    protected $collection;
38
39
    /**
40
     *
41
     * @var string
42
     */
43
    protected $stubDir = __DIR__ . '/stubs';
44
45
    /**
46
     * String substitution
47
     *
48
     * @var string[]
49
     */
50
    protected $templateParameters = [];
51
52
    /**
53
     * Fields
54
     *
55
     * @var Field[]
56
     */
57
    protected $cardFields = [];
58
59
    public function __construct(FrameworkComposer $composer, Model $model)
60
    {
61
        $this->composer = $composer;
62
        $this->model = $model;
63
        $this->setName($model->getName());
64
        $this->buildTemplateParameters();
65
    }
66
67
    public function generate(): GeneratedCollection
68
    {
69
        $this->collection = new GeneratedCollection();
70
71
        /**
72
         * @var FrameworkVue $vue
73
         */
74
        $vue = $this->composer->getByName('Vue');
75
        // $blade = FrameworkComposer::getByName('Blade');
76
77
        if ($vue !== null) {
78
            $vue->setFieldModelVariable('model.');
0 ignored issues
show
Bug introduced by
The method setFieldModelVariable() does not exist on Formularium\Frontend\Vue\Framework. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

78
            $vue->/** @scrutinizer ignore-call */ 
79
                  setFieldModelVariable('model.');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
79
            $this->makeJSModel();
80
            $this->makeVue($vue, 'Card', 'viewable');
81
            $this->makeVue($vue, 'List', 'viewable');
82
            $this->makeVue($vue, 'Table', 'viewable');
83
            $this->makeVue($vue, 'TableItem', 'viewable');
84
            $this->makeVue($vue, 'Show', 'viewable');
85
            $this->makeVue($vue, 'Edit', 'editable');
86
            $this->makeVue($vue, 'Form', 'editable');
87
            $this->makeVueRoutes();
88
            $this->makeVueIndex();
89
        }
90
91
        $this->makeGraphql();
92
93
        return $this->collection;
94
    }
95
96
    protected function buildTemplateParameters(): void
97
    {
98
        $this->cardFields = $this->model->filterField(
99
            function (Field $field) {
100
                return $field->getRenderable('card', false);
101
            }
102
        );
103
104
        $this->templateParameters = [
105
            'submitButton' => $this->composer->element('Button', [Element::LABEL => 'Submit'])
106
        ];
107
    }
108
109
    public function templateCallback(string $stub, FrameworkVue $vue, array $data, Model $m): string
0 ignored issues
show
Unused Code introduced by
The parameter $vue is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

109
    public function templateCallback(string $stub, /** @scrutinizer ignore-unused */ FrameworkVue $vue, array $data, Model $m): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $m is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

109
    public function templateCallback(string $stub, FrameworkVue $vue, array $data, /** @scrutinizer ignore-unused */ Model $m): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
110
    {
111
        $x = $this->templateFile(
112
            $stub,
113
            array_merge(
114
                $this->templateParameters,
115
                $data
116
            )
117
        );
118
        return $x;
119
    }
120
121
    protected function makeVue(FrameworkVue $vue, string $component, string $mode): void
122
    {
123
        $path = $this->model->getName() . '/' .
124
            $this->model->getName() . $component . '.vue';
125
126
        $stub = $this->stubDir . "/Vue{$component}.mustache.vue";
127
128
        if ($mode == 'editable') {
129
            $vue->setEditableTemplate(
130
                function (FrameworkVue $vue, array $data, Model $m) use ($stub) {
131
                    return $this->templateCallback($stub, $vue, $data, $m);
132
                }
133
            );
134
135
            $this->collection->push(
136
                new GeneratedItem(
137
                    GeneratedItem::TYPE_FRONTEND,
138
                    $this->model->editable($this->composer),
139
                    $path
140
                )
141
            );
142
        } else {
143
            $vue->setViewableTemplate(
144
                function (FrameworkVue $vue, array $data, Model $m) use ($stub) {
145
                    return $this->templateCallback($stub, $vue, $data, $m);
146
                }
147
            );
148
149
            $this->collection->push(
150
                new GeneratedItem(
151
                    GeneratedItem::TYPE_FRONTEND,
152
                    $this->model->viewable($this->composer, []),
153
                    $path
154
                )
155
            );
156
        }
157
    }
158
159
    protected function getFilters(): array
160
    {
161
        $filters = [];
162
        return $filters;
163
    }
164
165
    protected function makeGraphql(): void
166
    {
167
        $cardFieldNames = array_map(
168
            function (Field $field) {
169
                return $field->getName();
170
            },
171
            $this->cardFields
172
        );
173
        $cardFieldParameters = implode("\n", $cardFieldNames);
174
175
        $listQuery = <<<EOF
176
query (\$page: Int!) {
177
    {$this->lowerNamePlural}(page: \$page) {
178
        data {
179
            id
180
            $cardFieldParameters
181
        }
182
      
183
        paginatorInfo {
184
            currentPage
185
            perPage
186
            total
187
            lastPage
188
        }
189
    }
190
}
191
EOF;
192
193
        $this->collection->push(
194
            new GeneratedItem(
195
                GeneratedItem::TYPE_FRONTEND,
196
                $listQuery,
197
                $this->model->getName() . '/queryList.graphql'
198
            )
199
        );
200
201
        $itemQuery = <<<EOF
202
query (\$id: ID!) {
203
    {$this->lowerName}(id: \$id) {
204
        id
205
        TODO
206
    }
207
}
208
EOF;
209
210
        $this->collection->push(
211
            new GeneratedItem(
212
                GeneratedItem::TYPE_FRONTEND,
213
                $itemQuery,
214
                $this->model->getName() . '/queryItem.graphql'
215
            )
216
        );
217
218
        // TODO: variables
219
        $createMutation = <<<EOF
220
mutation create(\$name: String!) {
221
    {$this->lowerName}Create(name: \$name) {
222
        TODO
223
    }
224
}
225
EOF;
226
        $this->collection->push(
227
            new GeneratedItem(
228
                GeneratedItem::TYPE_FRONTEND,
229
                $createMutation,
230
                $this->model->getName() . '/mutationCreate.graphql'
231
            )
232
        );
233
    }
234
235
    protected function makeVueIndex(): void
236
    {
237
        $path = $this->model->getName() . '/index.js';
238
        $name = $this->studlyName;
239
240
        $items = [
241
            'Card',
242
            'Edit',
243
            'List',
244
            'Show',
245
        ];
246
247
        $import = array_map(
248
            function ($i) use ($name) {
249
                return "import {$name}$i from './{$name}$i.vue';";
250
            },
251
            $items
252
        );
253
254
        $export = array_map(
255
            function ($i) use ($name) {
256
                return "    {$name}$i,\n";
257
            },
258
            $items
259
        );
260
261
        $this->collection->push(
262
            new GeneratedItem(
263
                GeneratedItem::TYPE_FRONTEND,
264
                implode("\n", $import) . "\n" .
265
                "export {\n" .
266
                implode("\n", $export) . "\n};\n",
267
                $path
268
            )
269
        );
270
    }
271
272
    protected function makeVueRoutes(): void
273
    {
274
        $path = $this->model->getName() . '/routes.js';
275
276
        $this->collection->push(
277
            new GeneratedItem(
278
                GeneratedItem::TYPE_FRONTEND,
279
                $this->templateFile($this->stubDir . "/routes.mustache.js"),
280
                $path
281
            )
282
        );
283
    }
284
285
    protected function makeJSModel(): void
286
    {
287
        $path = $this->model->getName() . '/model.js';
288
        $modelJS = 'const model = ' . json_encode($this->model->getDefault()) .
289
            ";\n\nexport default model;\n";
290
        
291
        $this->collection->push(
292
            new GeneratedItem(
293
                GeneratedItem::TYPE_FRONTEND,
294
                $modelJS,
295
                $path
296
            )
297
        );
298
    }
299
}
300