Passed
Push — master ( 0d0893...6bf0b5 )
by Bruno
05:45 queued 11s
created

Framework::editableCompose()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 69
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 3
eloc 55
c 4
b 0
f 0
nc 3
nop 3
dl 0
loc 69
rs 8.9818

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 Formularium\Frontend\Vue;
4
5
use Formularium\Datatype;
6
use Formularium\Datatype\Datatype_bool;
7
use Formularium\Datatype\Datatype_number;
8
use Formularium\HTMLElement;
9
use Formularium\Model;
10
11
class Framework extends \Formularium\Framework
12
{
13
    const VUE_MODE_SINGLE_FILE = 'VUE_MODE_SINGLE_FILE';
14
    const VUE_MODE_EMBEDDED = 'VUE_MODE_EMBEDDED';
15
16
    const VUE_PROP = 'VUE_PROP';
17
18
19
    /**
20
     * @var string
21
     */
22
    protected $mode = self::VUE_MODE_EMBEDDED;
23
24
    /**
25
    * The tag used as container for fields in viewable()
26
    *
27
    * @var string
28
    */
29
    protected $viewableContainerTag = 'div';
30
31
    /**
32
     * The tag used as container for fields in editable()
33
     *
34
     * @var string
35
     */
36
    protected $editableContainerTag = 'div';
37
38
    /**
39
     * The viewable template.
40
     *
41
     * The following variables are replaced:
42
     *
43
     * {{form}}
44
     * {{jsonData}}
45
     * {{containerTag}}
46
     *
47
     * @var string
48
     */
49
    protected $viewableTemplate = '';
50
51
    /**
52
     *
53
     *
54
     * @var string
55
     */
56
    protected $editableTemplate = '';
57
58
    public function __construct(string $name = 'Vue')
59
    {
60
        parent::__construct($name);
61
    }
62
63
    /**
64
     * Static counter to generate unique ids.
65
     *
66
     * @return integer
67
     */
68
    public static function counter(): int
69
    {
70
        static $counter = 0;
71
        return $counter++;
72
    }
73
74
    /**
75
     * Get the tag used as container for fields in viewable()
76
     *
77
     * @return  string
78
     */
79
    public function getViewableContainerTag(): string
80
    {
81
        return $this->viewableContainerTag;
82
    }
83
84
    /**
85
     * Set the tag used as container for fields in viewable()
86
     *
87
     * @param  string  $viewableContainerTag  The tag used as container for fields in viewable()
88
     *
89
     * @return  self
90
     */
91
    public function setViewableContainerTag(string $viewableContainerTag): Framework
92
    {
93
        $this->viewableContainerTag = $viewableContainerTag;
94
        return $this;
95
    }
96
97
    public function getEditableContainerTag(): string
98
    {
99
        return $this->editableContainerTag;
100
    }
101
    
102
    /**
103
     * @param string $tag
104
     * @return self
105
     */
106
    public function setEditableContainerTag(string $tag): Framework
107
    {
108
        $this->editableContainerTag = $tag;
109
        return $this;
110
    }
111
112
    /**
113
     * Get the value of editableTemplate
114
     */
115
    public function getEditableTemplate(): string
116
    {
117
        return $this->editableTemplate;
118
    }
119
120
    /**
121
     * Set the value of editableTemplate
122
     *
123
     * @return self
124
     */
125
    public function setEditableTemplate(string $editableTemplate): Framework
126
    {
127
        $this->editableTemplate = $editableTemplate;
128
129
        return $this;
130
    }
131
    
132
    /**
133
     * Get {{containerTag}}
134
     *
135
     * @return  string
136
     */
137
    public function getViewableTemplate()
138
    {
139
        return $this->viewableTemplate;
140
    }
141
142
    /**
143
     * Set {{containerTag}}
144
     *
145
     * @param  string  $viewableTemplate  {{containerTag}}
146
     *
147
     * @return  self
148
     */
149
    public function setViewableTemplate(string $viewableTemplate)
150
    {
151
        $this->viewableTemplate = $viewableTemplate;
152
153
        return $this;
154
    }
155
    
156
    /**
157
     * Sets the vue render mode, single file component or embedded
158
     *
159
     * @param string $mode self::VUE_MODE_EMBEDDED or self::VUE_MODE_SINGLE_FILE
160
     * @return Framework
161
     */
162
    public function setMode(string $mode): Framework
163
    {
164
        $this->mode = $mode;
165
        return $this;
166
    }
167
168
    /**
169
     * Get the value of mode
170
     *
171
     * @return string
172
     */
173
    public function getMode(): string
174
    {
175
        return $this->mode;
176
    }
177
178
    public function htmlHead(HTMLElement &$head)
179
    {
180
        $head->prependContent(
181
            HTMLElement::factory('script', ['src' => "https://cdn.jsdelivr.net/npm/vue/dist/vue.js"])
182
        );
183
    }
184
185
    protected function mapType(Datatype $type): string
186
    {
187
        if ($type instanceof Datatype_number) {
188
            return 'Number';
189
        } elseif ($type instanceof Datatype_bool) {
190
            return 'Boolean';
191
        }
192
        return 'String';
193
    }
194
195
    protected function props(Model $m): array
196
    {
197
        $props = [];
198
        foreach ($m->getFields() as $field) {
199
            if ($field->getExtension(self::VUE_PROP, false)) { // TODO
200
                $p = [
201
                    'type' => $this->mapType($field->getDatatype()),
202
                ];
203
                if ($field->getExtension(Datatype::REQUIRED, false)) {
204
                    $p['required'] = true;
205
                }
206
                $props[$field->getName()] = $p;
207
            }
208
        }
209
        return $props;
210
    }
211
212
    public function viewableCompose(Model $m, array $elements, string $previousCompose): string
213
    {
214
        $data = $m->getDefault(); // TODO: load data
215
        
216
        $viewableForm = join('', $elements);
217
        $jsonData = json_encode($data);
218
        $templateData = [
219
            'containerTag' => $this->getViewableContainerTag(),
220
            'form' => $viewableForm,
221
            'jsonData' => $jsonData,
222
            'props' => $this->props($m)
223
        ];
224
225
        if ($this->viewableTemplate) {
226
            return $this->fillTemplate(
227
                $this->viewableTemplate,
228
                $templateData,
229
                $m
230
            );
231
        } elseif ($this->mode === self::VUE_MODE_SINGLE_FILE) {
232
            $viewableTemplate = <<<EOF
0 ignored issues
show
Unused Code introduced by
The assignment to $viewableTemplate is dead and can be removed.
Loading history...
233
<template>
234
<{{containerTag}}>
235
    {{form}}
236
</{{containerTag}}>
237
</template>
238
<script>
239
module.exports = {
240
    data: function () {
241
        return {{jsonData}};
242
    }
243
};
244
</script>
245
<style>
246
</style>
247
EOF;
248
            return $this->fillTemplate(
249
                $this->viewableTemplate,
250
                $templateData,
251
                $m
252
            );
253
        } else {
254
            $id = 'vueapp' . static::counter();
255
            $t = new HTMLElement($this->getViewableContainerTag(), ['id' => $id], $viewableForm, true);
256
            $script = <<<EOF
257
var app = new Vue({
258
    el: '#$id',
259
    data: $jsonData
260
});
261
EOF;
262
            $s = new HTMLElement('script', [], $script, true);
263
            return HTMLElement::factory('div', [], [$t, $s])->getRenderHTML();
264
        }
265
    }
266
267
    public function editableCompose(Model $m, array $elements, string $previousCompose): string
268
    {
269
        $data = $m->getDefault(); // TODO: load data
270
        $editableContainerTag = $this->getEditableContainerTag();
271
        $editableForm = join('', $elements);
272
        $jsonData = json_encode($data);
273
        $templateData = [
274
            'containerTag' => $this->getViewableContainerTag(),
275
            'form' => $editableForm,
276
            'jsonData' => $jsonData,
277
            'props' => $this->props($m)
278
        ];
279
280
        $methods = <<<EOF
281
    methods: {
282
        changedFile(name, event) {
283
            console.log(name, event);
284
            const input = event.target;
285
            const files = input.files;
286
            if (files && files[0]) {
287
                // input.preview = window.URL.createObjectURL(files[0]);
288
            }
289
        }
290
    }        
291
EOF;
292
293
        if ($this->viewableTemplate) {
294
            return $this->fillTemplate(
295
                $this->editableTemplate,
296
                $templateData,
297
                $m
298
            );
299
        } elseif ($this->mode === self::VUE_MODE_SINGLE_FILE) {
300
            $editableTemplate = <<<EOF
301
<template>
302
<{{containerTag}}>
303
    {{form}}
304
</{{containerTag}}>
305
</template>
306
<script>
307
module.exports = {
308
    data: function () {
309
        return {{jsonData}};
310
    },
311
    $methods
312
};
313
</script>
314
<style>
315
</style>
316
EOF;
317
            return $this->fillTemplate(
318
                $editableTemplate,
319
                $templateData,
320
                $m
321
            );
322
        } else {
323
            $id = 'vueapp' . static::counter();
324
            $t = new HTMLElement($editableContainerTag, ['id' => $id], $editableForm, true);
325
            $script = <<<EOF
326
var app = new Vue({
327
    el: '#$id',
328
    data: function () {
329
        return $jsonData;
330
    },
331
    $methods
332
});
333
EOF;
334
            $s = new HTMLElement('script', [], $script, true);
335
            return HTMLElement::factory('div', [], [$t, $s])->getRenderHTML();
336
        }
337
    }
338
339
    protected function fillTemplate(string $template, array $data, Model $m): string
340
    {
341
        $template = str_replace(
342
            '{{form}}',
343
            $data['form'],
344
            $template
345
        );
346
        $template = str_replace(
347
            '{{modelName}}',
348
            $m->getName(),
349
            $template
350
        );
351
        $template = str_replace(
352
            '{{modelNameLower}}',
353
            mb_strtolower($m->getName()),
354
            $template
355
        );
356
        $template = str_replace(
357
            '{{jsonData}}',
358
            $data['jsonData'],
359
            $template
360
        );
361
        $template = str_replace(
362
            '{{containerTag}}',
363
            $data['containerTag'],
364
            $template
365
        );
366
        return $template;
367
    }
368
}
369