Passed
Push — master ( fd0391...6bafc6 )
by Bruno
04:22
created

buildComposer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 6
c 1
b 1
f 0
dl 0
loc 12
rs 10
cc 2
nc 2
nop 1
1
<?php declare(strict_types=1);
2
3
require(__DIR__ . '/../vendor/autoload.php');
4
5
use Formularium\Datatype;
6
use Formularium\Factory\DatatypeFactory;
7
use Formularium\Element;
8
use Formularium\Exception\ClassNotFoundException;
9
use Formularium\Formularium;
10
use Formularium\Framework;
11
use Formularium\FrameworkComposer;
12
use Formularium\Frontend\HTML\Element\Button;
13
use Formularium\Frontend\HTML\Element\Card;
14
use Formularium\Frontend\HTML\Element\Pagination;
15
use Formularium\Frontend\HTML\Element\Table;
16
use Formularium\Frontend\HTML\Renderable\Renderable_enum;
17
use Formularium\Frontend\HTML\Renderable\Renderable_number;
18
use Formularium\Frontend\Vue\Framework as VueFramework;
19
use Formularium\HTMLNode;
20
use Formularium\Model;
21
use Formularium\Renderable;
22
use Formularium\Validator\Max;
23
use Formularium\Validator\MaxLength;
24
use Formularium\Validator\Min;
25
use Formularium\Validator\MinLength;
26
27
function templatify(FrameworkComposer $frameworkComposer, string $templateName, string $contents, string $title)
28
{
29
    $head = $frameworkComposer->htmlHead();
30
    $footer = $frameworkComposer->htmlFooter();
31
32
    $frameworkNames = join(
33
        '/',
34
        array_map(
35
            function (Framework $f) {
36
                return $f->getName();
37
            },
38
            $frameworkComposer->getFrameworks()
39
        )
40
    );
41
    $template = file_get_contents(__DIR__ . '/kitchentemplates/' . $templateName);
42
43
    $template = strtr(
44
        $template,
45
        [
46
            '{{frameworkNames}}' => $frameworkNames,
47
            '{{title}}' => $title,
48
            '{{head}}' => $head,
49
            '{{contents}}' => $contents,
50
            '{{footer}}' => $footer,
51
        ]
52
    );
53
    return $template;
54
}
55
56
function buildComposer(array $frameworkNames): FrameworkComposer
57
{
58
    $frameworkComposer = FrameworkComposer::create($frameworkNames);
59
    if ($frameworkComposer->getByName('Vuetify')) {
60
        /**
61
         * @var VueFramework
62
         */
63
        $vue = $frameworkComposer->getByName('Vue');
64
        $vue->getVueCode()
0 ignored issues
show
Bug introduced by
The method getVueCode() does not exist on Formularium\Framework. It seems like you code against a sub-type of Formularium\Framework such as 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

64
        $vue->/** @scrutinizer ignore-call */ 
65
              getVueCode()
Loading history...
65
            ->appendOther('vuetify', 'new Vuetify()');
66
    }
67
    return $frameworkComposer;
68
}
69
70
function generateBase(array $frameworkNames, string $templateName)
71
{
72
    $frameworkComposer = buildComposer($frameworkNames);
73
74
    /*
75
     * basic demo fiels
76
     */
77
    $basicFields = [
78
        'myString' => [
79
            'datatype' => 'string',
80
            'validators' => [
81
                MinLength::class => [ 'value' => 3 ],
82
                MaxLength::class => [ 'value' => 30 ],
83
                Datatype::REQUIRED => [ 'value' => true ],
84
            ],
85
            'renderable' => [
86
                Renderable::LABEL => 'Type string',
87
                Renderable::COMMENT => 'Some text explaining this field. Must be between 3 and 30 characters.',
88
                Renderable::PLACEHOLDER => "Type here",
89
                Renderable::SIZE => Renderable::SIZE_LARGE,
90
                Renderable::ICON_PACK => 'fas',
91
                Renderable::ICON => 'fa-check',
92
            ],
93
        ],
94
        'myInteger' => [
95
            'datatype' => 'integer',
96
            'validators' => [
97
                Min::class => [ 'value' => 4],
98
                Max::class => [ 'value' => 40],
99
            ],
100
            'renderable' => [
101
                Renderable_number::STEP => 2,
102
                Renderable::LABEL => 'Type integer (between 4 and 40)',
103
                Renderable::PLACEHOLDER => "Type here"
104
            ],
105
        ],
106
        'ipv4example' => [
107
            'datatype' => 'ipv4',
108
            'renderable' => [
109
                Renderable::LABEL => 'An IP, such as 192.168.0.1'
110
            ],
111
        ],
112
        'countrycodeselect' => [
113
            'datatype' => 'countrycodeiso3',
114
            'renderable' => [
115
                Renderable_enum::FORMAT_CHOOSER => Renderable_enum::FORMAT_CHOOSER_SELECT,
116
                Renderable::LABEL => 'Country code - select choice'
117
            ],
118
        ],
119
    ];
120
121
    // generate basic model
122
    $basicModel = Model::fromStruct(
123
        [
124
            'name' => 'BasicModel',
125
            'fields' => $basicFields
126
        ]
127
    );
128
129
    $submitButton = $frameworkComposer->nodeElement(
130
        'Button',
131
        [
132
            Element::LABEL => 'Save',
133
            Button::COLOR => Button::COLOR_PRIMARY,
134
            Button::TYPE => 'submit'
135
        ]
136
    );
137
138
    $frameworkComposer->appendFooterElement($submitButton);
139
    $basicDemoEditable = $basicModel->editable($frameworkComposer, []);
140
    return templatify($frameworkComposer, $templateName, $basicDemoEditable, 'Basic demo');
141
}
142
143
function generateElements(array $frameworkNames, string $templateName)
144
{
145
    $frameworkComposer = buildComposer($frameworkNames);
146
147
    $wrapNode = function (string $title, HTMLNode $node) use ($frameworkComposer) {
148
        $frameworkComposer->appendFooterElement(
149
            new HTMLNode(
150
                'section',
151
                [ "class" => "spaced" ],
152
                [new HTMLNode('h3', [], $title), $node ]
153
            )
154
        );
155
    };
156
157
    $upload = $frameworkComposer->nodeElement(
158
        'Upload',
159
        [
160
        ]
161
    );
162
    $wrapNode('Upload', $upload);
163
164
    $submitButton = $frameworkComposer->nodeElement(
165
        'Button',
166
        [
167
            Element::LABEL => 'Save',
168
            Button::COLOR => Button::COLOR_PRIMARY,
169
            Button::TYPE => 'submit'
170
        ]
171
    );
172
    $wrapNode('Button', $submitButton);
173
174
    $table = $frameworkComposer->nodeElement(
175
        'Table',
176
        [
177
            Table::ROW_NAMES => ['First', 'Second', 'Third'],
178
            Table::ROW_DATA => [ ['a', 'b', 'c'], [ 'd', 'e', 'f'] ],
179
            Table::STRIPED => true
180
        ]
181
    );
182
    $wrapNode('Table', $table);
183
184
    $pagination = $frameworkComposer->nodeElement(
185
        'Pagination',
186
        [
187
            Pagination::CURRENT => 21,
188
            Pagination::CURRENT_PAGE => 2, // should have only CURRENT or CURRENT_PAGE, but depends on framework
189
            Pagination::TOTAL_ITEMS => 203,
190
        ]
191
    );
192
    $wrapNode('Pagination', $pagination);
193
194
    $card = $frameworkComposer->nodeElement(
195
        'Card',
196
        [
197
            Card::TITLE => 'Card title',
198
            Card::IMAGE => 'https://via.placeholder.com/150',
199
            Card::CONTENT => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '
200
        ]
201
    );
202
    $wrapNode('Card', $card);
203
204
    $spinner = $frameworkComposer->nodeElement(
205
        'Spinner',
206
        [
207
        ]
208
    );
209
    $wrapNode('Spinner', $spinner);
210
211
    $basicModel = Model::fromStruct(
212
        [
213
            'name' => 'BasicModel',
214
            'fields' => []
215
        ]
216
    );
217
218
    $vue = $frameworkComposer->getByName('Vue');
219
    if ($vue) {
220
        /**
221
         * @var \Formularium\Frontend\Vue\Framework $vue
222
         */
223
        $vue->getVueCode()->appendExtraData('file', '');
224
        $vue->getVueCode()->appendExtraData('paginator', [ "currentPage" => 1, "totalItems" => 203 ]);
225
    }
226
227
    $html = $basicModel->editable($frameworkComposer, []);
228
229
    return templatify($frameworkComposer, $templateName, $html, 'Elements');
230
}
231
232
function kitchenSink(array $frameworkNames, string $templateName)
233
{
234
    $frameworkComposer = buildComposer($frameworkNames);
235
236
    /*
237
     * kitchen sink fields
238
     */
239
    $fields = [];
240
    $datatypes = DatatypeFactory::getNames();
241
242
    // make a default for all types
243
    foreach ($datatypes as $d) {
244
        try {
245
            DatatypeFactory::factory($d);
246
            $fields[$d] = [
247
                'datatype' => $d,
248
                'renderable' => [
249
                    Renderable::LABEL => 'Type ' . $d
250
                ],
251
            ];
252
        } catch (ClassNotFoundException $e) {
253
            // Abstract class
254
        }
255
    }
256
257
    // generate kitchen sink model
258
    $model = Model::fromStruct(
259
        [
260
            'name' => 'TestModel',
261
            'fields' => $fields
262
        ]
263
    );
264
    $randomData = [];
265
    foreach ($model->getFields() as $f) {
266
        if ($f->getDatatype()->getBasetype() !== 'constant') {
267
            $randomData[$f->getName()] = $f->getDatatype()->getRandom();
268
        }
269
    }
270
    $modelViewable = $model->viewable($frameworkComposer, $randomData);
271
    $modelEditable = $model->editable($frameworkComposer);
272
273
    return [
274
        templatify($frameworkComposer, $templateName, $modelViewable, 'Model Viewable'),
275
        templatify($frameworkComposer, $templateName, $modelEditable, 'Model editable')
276
    ];
277
}
278
279
function main()
280
{
281
    @mkdir(__DIR__ . '/../docs/');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

281
    /** @scrutinizer ignore-unhandled */ @mkdir(__DIR__ . '/../docs/');

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
282
    @mkdir(__DIR__ . '/../docs/kitchensink/');
283
    $path = __DIR__ . '/../Formularium/Frontend/';
284
    $dir = scandir($path);
285
    if ($dir === false) {
286
        echo 'Cannot find frontend';
287
        return 1;
288
    }
289
    $frameworks = array_diff($dir, array('.', '..'));
0 ignored issues
show
Unused Code introduced by
The assignment to $frameworks is dead and can be removed.
Loading history...
290
    $index = <<<EOF
291
<!DOCTYPE html>
292
<html>
293
<head>
294
<head>
295
    <meta charset="UTF-8">
296
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
297
    <meta name="viewport" content="width=device-width, initial-scale=1">
298
299
    <title>Formularium Kitchen Sink</title>
300
    <meta property="og:title" content="Formularium">
301
    <meta property="og:locale" content="en_US">
302
    <meta name="description" content="Form validation and generation for PHP with custom frontend generators">
303
    <meta property="og:description" content="Form validation and generation for PHP with custom frontend generators">
304
    <link rel="canonical" href="https://corollarium.github.io/Formularium/">
305
    <meta property="og:url" content="https://corollarium.github.io/Formularium/">
306
    <meta property="og:site_name" content="Formularium">
307
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
308
</head>
309
<body>
310
<div class="container">
311
<h1>Formularium Examples</h1>
312
<p>These files are all automatically generated from the same data models, using different frameworks.</p>
313
314
<div>
315
EOF;
316
    $frameworks = [
317
        ['framework' => ['HTML', 'HTMLValidation', 'Quill'], 'template' => 'base'],
318
        ['framework' => ['HTML', 'HTMLValidation', 'Bulma', 'Quill'], 'template' => 'bulma'],
319
        ['framework' => ['HTML', 'HTMLValidation', 'Bootstrap', 'Quill'], 'template' => 'base'],
320
        ['framework' => ['HTML', 'HTMLValidation', 'Bootstrap', 'Quill', 'Parsley'], 'template' => 'base'],
321
        ['framework' => ['HTML', 'HTMLValidation', 'Bootstrap', 'Vue', 'Vuelidate'], 'template' => 'base'],
322
        ['framework' => ['HTML', 'HTMLValidation', 'Bootstrapvue', 'Vue'], 'template' => 'base'],
323
        ['framework' => ['HTML', 'HTMLValidation', 'Materialize'], 'template' => 'base'],
324
        ['framework' => ['HTML', 'HTMLValidation', 'Bulma', 'Quill', 'Vue'], 'template' => 'bulma'],
325
        ['framework' => ['HTML', 'HTMLValidation', 'Bootstrap', 'Vue'], 'template' => 'base'],
326
        ['framework' => ['HTML', 'HTMLValidation', 'Buefy', 'Vue'], 'template' => 'bulma'],
327
        ['framework' => ['HTML', 'HTMLValidation', 'React'], 'template' => 'base'],
328
        ['framework' => ['HTML', 'HTMLValidation', 'Bootstrap', 'React'], 'template' => 'base'],
329
        ['framework' => ['HTML', 'HTMLValidation', 'Vuetify', 'Vue'], 'template' => 'base'],
330
    ];
331
    foreach ($frameworks as $f) {
332
        $name = join('', $f['framework']);
333
        $prettyName = join(' + ', array_slice($f['framework'], 2));
334
        echo "Building $name...\n";
335
336
        $index .= "<h2>$prettyName</h2><ul>";
337
338
        $html = generateBase($f['framework'], $f['template'] . '_demo.html');
339
        $filename = __DIR__ . '/../docs/kitchensink/demo_' . $name . '.html';
340
        file_put_contents($filename, $html);
341
        $index .= "<li><a href='{$filename}'>Basic example</a></li>";
342
343
        $html = generateElements($f['framework'], $f['template'] . '_demo.html');
344
        $filename = __DIR__ . '/../docs/kitchensink/elements_' . $name . '.html';
345
        file_put_contents($filename, $html);
346
        $index .= "<li><a href='{$filename}'>Basic elements</a></li>";
347
348
        $html = kitchenSink($f['framework'], $f['template'] . '_demo.html');
349
        $filename = __DIR__ . '/../docs/kitchensink/viewable_' . $name . '.html';
350
        file_put_contents($filename, $html[0]);
351
        $index .= "<li><a href='{$filename}'>Viewable (all data types)</a></li>";
352
        $filename = __DIR__ . '/../docs/kitchensink/editable_' . $name . '.html';
353
        file_put_contents($filename, $html[1]);
354
        $index .= "<li><a href='{$filename}'>Editable (all data types)</a></li>";
355
356
        // $html = kitchenSink($f['framework'], $f['template']);
357
        // file_put_contents(__DIR__ . '/../docs/kitchensink/' . $name . '.html', $html);
358
359
        $index .= "</ul>";
360
    }
361
    $index .= "</div>
362
<footer>
363
    <a href='https://github.com/Corollarium/Formularium/'>Formularium Source code</a> and <a href='https://corollarium.github.io/Formularium/'>Documentation</a>
364
</footer>
365
</div>
366
</body></html>";
367
    file_put_contents(__DIR__ . '/../docs/kitchensink/index.html', $index);
368
}
369
370
main();
371