Completed
Push — master ( 6d6774...64f3ed )
by Jeroen
11:23 queued 05:13
created

GeneratorBundle/Generator/PagePartGenerator.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\GeneratorBundle\Generator;
4
5
use Faker\Provider\Base;
6
use Faker\Provider\DateTime;
7
use Faker\Provider\Lorem;
8
use Symfony\Component\DependencyInjection\Container;
9
use Symfony\Component\Finder\Finder;
10
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
11
use Symfony\Component\Yaml\Yaml;
12
13
/**
14
 * Generates all classes/files for a new pagepart
15
 */
16
class PagePartGenerator extends KunstmaanGenerator
17
{
18
    /**
19
     * @var BundleInterface
20
     */
21
    private $bundle;
22
23
    /**
24
     * @var string
25
     */
26
    private $entity;
27
28
    /**
29
     * @var string
30
     */
31
    private $prefix;
32
33
    /**
34
     * @var array
35
     */
36
    private $fields;
37
38
    /**
39
     * @var array
40
     */
41
    private $sections;
42
43
    /**
44
     * Generate the pagepart.
45
     *
46
     * @param BundleInterface $bundle    The bundle
47
     * @param string          $entity    The entity name
48
     * @param string          $prefix    The database prefix
49
     * @param array           $fields    The fields
50
     * @param array           $sections  The page sections
51
     * @param bool            $behatTest If we need to generate a behat test for this pagepart
52
     *
53
     * @throws \RuntimeException
54
     */
55 View Code Duplication
    public function generate(BundleInterface $bundle, $entity, $prefix, array $fields, array $sections, $behatTest)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
56
    {
57
        $this->bundle = $bundle;
58
        $this->entity = $entity;
59
        $this->prefix = $prefix;
60
        $this->fields = $fields;
61
        $this->sections = $sections;
62
63
        $this->generatePagePartEntity();
64
        $this->generateFormType();
65
        $this->generateResourceTemplate();
66
        $this->generateSectionConfig();
67
        if ($behatTest) {
68
            $this->generateBehatTest();
69
        }
70
    }
71
72
    /**
73
     * Generate the pagepart entity.
74
     *
75
     * @throws \RuntimeException
76
     */
77
    private function generatePagePartEntity()
78
    {
79
        if (file_exists($this->bundle->getPath() . '/Entity/PageParts/AbstractPagePart.php')) {
80
            $abstractClass = $this->bundle->getNamespace() . '\Entity\PageParts\AbstractPagePart';
81
        } else {
82
            $abstractClass = 'Kunstmaan\PagePartBundle\Entity\AbstractPagePart';
83
        }
84
85
        list($entityCode, $entityPath) = $this->generateEntity(
86
            $this->bundle,
87
            $this->entity,
88
            $this->fields,
89
            'PageParts',
90
            $this->prefix,
91
            $abstractClass
92
        );
93
94
        // Add some extra functions in the generated entity :s
95
        $params = array(
96
            'bundle' => $this->bundle->getName(),
97
            'pagepart' => $this->entity,
98
            'adminType' => '\\' . $this->bundle->getNamespace() . '\\Form\\PageParts\\' . $this->entity . 'AdminType',
99
            'isV4' => $this->isSymfony4(),
100
        );
101
        $extraCode = $this->render('/Entity/PageParts/ExtraFunctions.php', $params);
102
103
        $pos = strrpos($entityCode, "\n}");
104
        $trimmed = substr($entityCode, 0, $pos);
105
        $entityCode = $trimmed."\n\n".$extraCode."\n}\n";
106
107
        // Write class to filesystem
108
        $this->filesystem->mkdir(dirname($entityPath));
109
        file_put_contents($entityPath, $entityCode);
110
111
        $this->assistant->writeLine('Generating entity : <info>OK</info>');
112
    }
113
114
    /**
115
     * Generate the admin form type entity.
116
     */
117
    private function generateFormType()
118
    {
119
        $this->generateEntityAdminType($this->bundle, $this->entity, 'PageParts', $this->fields);
120
121
        $this->assistant->writeLine('Generating form type : <info>OK</info>');
122
    }
123
124
    /**
125
     * Generate the twig template.
126
     */
127
    private function generateResourceTemplate()
128
    {
129
        $savePath = $this->getTemplateDir($this->bundle) . '/PageParts/'.$this->entity.'/view.html.twig';
130
131
        $params = array(
132
            'pagepart' => strtolower(
133
                    preg_replace('/([a-z])([A-Z])/', '$1-$2', str_ireplace('PagePart', '', $this->entity))
134
                ) . '-pp',
135
            'fields' => $this->fields,
136
        );
137
        $this->renderFile('/Resources/views/PageParts/view.html.twig', $savePath, $params);
138
139
        $this->assistant->writeLine('Generating template : <info>OK</info>');
140
    }
141
142
    /**
143
     * Update the page section config files
144
     */
145
    private function generateSectionConfig()
146
    {
147
        if (count($this->sections) > 0) {
148 View Code Duplication
            if ($this->isSymfony4()) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
                $dir = $this->container->getParameter('kernel.project_dir') . '/config/kunstmaancms/pageparts/';
150
            } else {
151
                $dir = $this->bundle->getPath().'/Resources/config/pageparts/';
152
            }
153
154
            foreach ($this->sections as $section) {
155
                $data = Yaml::parse(file_get_contents($dir . $section));
156
157
                // grab the sf4 style data if needed
158
                if (array_key_exists('kunstmaan_page_part', $data) && array_key_exists('pageparts', $data['kunstmaan_page_part'])) {
159
                    $pagePartKey = array_keys($data['kunstmaan_page_part']['pageparts'])[0];
160
                    $data = $data['kunstmaan_page_part']['pageparts'][$pagePartKey];
161
                }
162
163
                if (!array_key_exists('types', $data)) {
164
                    $data['types'] = array();
165
                }
166
167
                $data['types'][] = array(
168
                    'name' => str_replace('PagePart', '', $this->entity),
169
                    'class' => $this->bundle->getNamespace() . '\\Entity\\PageParts\\' . $this->entity,
170
                );
171
172
                // restore the sf4 style data
173
                if (isset($pagePartKey)) {
174
                    $data = [
175
                        'kunstmaan_page_part' => [
176
                            'pageparts' => [$pagePartKey => $data],
177
                        ],
178
                    ];
179
                }
180
181
                $ymlData = Yaml::dump($data, 5);
182
                file_put_contents($dir . $section, $ymlData);
183
            }
184
185
            $this->assistant->writeLine('Updating section config : <info>OK</info>');
186
        }
187
    }
188
189
    /**
190
     * Generate the admin form type entity.
191
     */
192
    private function generateBehatTest()
193
    {
194
        $configDir = $this->bundle->getPath() . '/Resources/config';
195
196
        // Get the context names for each section config file
197
        $sectionInfo = array();
198
        $dir = $configDir . '/pageparts/';
199
        foreach ($this->sections as $section) {
200
            $data = Yaml::parse(file_get_contents($dir . $section));
201
            $sectionInfo[basename($section, '.yml')] = array('context' => $data['context'], 'pagetempates' => array());
202
        }
203
204
        /*
205
            Example $sectionInfo contents:
206
            Array
207
            (
208
                [main] => Array
209
                    (
210
                        [context] => main
211
                        [pagetempates] => Array
212
                            (
213
                            )
214
                    )
215
            )
216
        */
217
218
        // Get a list of page templates that use this context
219
        $templateFinder = new Finder();
220
        $templateFinder->files()->in($configDir . '/pagetemplates')->name('*.yml');
221
222
        $contextTemplates = array();
223
        foreach ($templateFinder as $templatePath) {
224
            $parts = explode('/', $templatePath);
225
            $fileName = basename($parts[count($parts) - 1], '.yml');
226
227
            $data = Yaml::parse(file_get_contents($templatePath));
228
            $templateName = $data['name'];
229
            if (array_key_exists('rows', $data) && is_array($data['rows'])) {
230
                foreach ($data['rows'] as $row) {
231
                    if (is_array($row) && array_key_exists('regions', $row) && is_array($row['regions'])) {
232
                        foreach ($row['regions'] as $region) {
233
                            $contextTemplates[$region['name']][$fileName] = $templateName;
234
                        }
235
                    }
236
                }
237
            }
238
        }
239
240
        /*
241
            Example $contextTemplates contents:
242
            Array
243
            (
244
                [main] => Array
245
                    (
246
                        [full-width-page] => Full width page
247
                        [homepage] => Home page
248
                        [sidebar-page] => Page with left sidebar
249
                    )
250
                [top] => Array
251
                    (
252
                        [homepage] => Home page
253
                    )
254
                [sidebar] => Array
255
                    (
256
                        [homepage] => Home page
257
                        [sidebar-page] => Page with left sidebar
258
                    )
259
            )
260
        */
261
262
        // Link the page templates to the sections
263
        foreach ($sectionInfo as $fileName => $info) {
264
            $context = $info['context'];
265
            if (array_key_exists($context, $contextTemplates)) {
266
                $sectionInfo[$fileName]['pagetempates'] = $contextTemplates[$context];
267
            }
268
        }
269
270
        /*
271
            Example $sectionInfo contents:
272
            Array
273
            (
274
                [main] => Array
275
                    (
276
                        [context] => main
277
                        [pagetempates] => Array
278
                            (
279
                                [full-width-page] => Full width page
280
                                [homepage] => Home page
281
                                [sidebar-page] => Page with left sidebar
282
                            )
283
284
                    )
285
286
            )
287
        */
288
289
        $folder = $this->registry->getRepository('KunstmaanMediaBundle:Folder')->findOneBy(array('rel' => 'image'));
290
        $images = $this->registry->getRepository('KunstmaanMediaBundle:Media')->findBy(
291
            array('folder' => $folder, 'deleted' => false),
292
            array(),
293
            2
294
        );
295
296
        // Get all the available pages
297
        $finder = new Finder();
298
        $finder->files()->in($this->bundle->getPath() . '/Entity/Pages')->name('*.php');
299
300
        $pages = array();
301
        foreach ($finder as $pageFile) {
302
            $parts = explode('/', $pageFile);
303
            $className = basename($parts[count($parts) - 1], '.php');
304
305
            $contents = file_get_contents($pageFile);
306
            if (strpos($contents, 'abstract class') === false && strpos($contents, 'interface ') === false && strpos($contents, 'trait ') === false) {
307
                $classNamespace = '\\' . $this->bundle->getNamespace() . '\Entity\Pages\\' . $className;
308
                $entity = new $classNamespace();
309
310
                if (!method_exists($entity, 'getPagePartAdminConfigurations') || !method_exists(
311
                        $entity,
312
                        'getPageTemplates'
313
                    )
314
                ) {
315
                    continue;
316
                }
317
318
                $ppConfigs = $entity->getPagePartAdminConfigurations();
319
                $ptConfigs = $entity->getPageTemplates();
320
321
                foreach ($ppConfigs as $ppConfig) {
322
                    $parts = explode(':', $ppConfig);
323
                    $ppConfigFilename = $parts[count($parts) - 1];
324
325
                    // Context found in this Page class
326
                    if (array_key_exists($ppConfigFilename, $sectionInfo)) {
327
                        // Search for templates
328
                        foreach ($ptConfigs as $ptConfig) {
329
                            $parts = explode(':', $ptConfig);
330
                            $ptConfigFilename = $parts[count($parts) - 1];
331
332
                            // Page template found
333
                            if (array_key_exists($ptConfigFilename, $sectionInfo[$ppConfigFilename]['pagetempates'])) {
334
                                // Get all page properties
335
                                $form = $this->container->get('form.factory')->create($entity->getDefaultAdminType());
336
                                $children = $form->createView()->children;
337
338
                                $pageFields = array();
339
                                foreach ($children as $field) {
340
                                    $name = $field->vars['name'];
341
                                    $attr = $field->vars['attr'];
342
                                    $blocks = $field->vars['block_prefixes'];
343
344
                                    if ($name == 'title' || $name == 'pageTitle') {
345
                                        continue;
346
                                    }
347
348
                                    if ($blocks[1] == 'hidden') {
349
                                        // do nothing
350
                                    } elseif ($blocks[1] == 'choice' && $blocks[1] == 'entity') {
351
                                        // do nothing
352
                                    } elseif ($blocks[1] == 'datetime') {
353
                                        $pageFields[]['datetime'] = array(
354
                                            'label' => $this->labelCase($name),
355
                                            'date_random' => DateTime::date('d/m/Y'),
356
                                            'time_random' => DateTime::time('H:i'),
357
                                        );
358
                                    } elseif ($blocks[1] == 'number') {
359
                                        $pageFields[]['decimal'] = array(
360
                                            'label' => $this->labelCase($name),
361
                                            'random' => Base::randomFloat(2, 0, 99999),
362
                                        );
363
                                    } elseif ($blocks[1] == 'integer') {
364
                                        $pageFields[]['integer'] = array(
365
                                            'label' => $this->labelCase($name),
366
                                            'random' => Base::randomNumber(3000, 99999),
367
                                        );
368
                                    } elseif ($blocks[1] == 'checkbox') {
369
                                        $pageFields[]['boolean'] = array(
370
                                            'label' => $this->labelCase($name),
371
                                        );
372
                                    } elseif ($blocks[1] == 'media') {
373
                                        $id = (count($images) > 0 ? $images[0]->getId() : 1);
374
                                        $pageFields[]['media'] = array(
375
                                            'label' => $this->labelCase($name),
376
                                            'random' => $id,
377
                                        );
378
                                    } elseif ($blocks[2] == 'urlchooser') {
379
                                        $pageFields[]['link'] = array(
380
                                            'label' => $this->labelCase($name),
381
                                            'random' => 'http://www.' . strtolower(Lorem::word()) . '.com',
382
                                        );
383
                                    } elseif ($blocks[2] == 'textarea' && array_key_exists(
384
                                            'class',
385
                                            $attr
386
                                        ) && $attr['class'] == 'js-rich-editor rich-editor'
387
                                    ) {
388
                                        $pageFields[]['rich_text'] = array(
389
                                            'label' => $this->labelCase($name),
390
                                            'random' => Lorem::sentence(),
391
                                        );
392
                                    } elseif ($blocks[2] == 'textarea' || $blocks[1] == 'text') {
393
                                        $pageFields[]['text'] = array(
394
                                            'label' => $this->labelCase($name),
395
                                            'random' => Lorem::word(),
396
                                        );
397
                                    }
398
                                }
399
400
                                $pages[] = array(
401
                                    'name' => $className,
402
                                    'section' => $sectionInfo[$ppConfigFilename]['context'],
403
                                    'template' => $sectionInfo[$ppConfigFilename]['pagetempates'][$ptConfigFilename],
404
                                    'fields' => $pageFields,
405
                                );
406
                            }
407
                        }
408
                    }
409
                }
410
            }
411
        }
412
413
        /*
414
            Example $pages contents:
415
            Array
416
            (
417
                [0] => Array
418
                    (
419
                        [name] => ContentPage
420
                        [section] => main
421
                        [template] => Page with left sidebar
422
                        [fields] => Array
423
                            (
424
                                ...
425
                            )
426
                    )
427
                [1] => Array
428
                    (
429
                        [name] => ContentPage
430
                        [section] => main
431
                        [template] => Full width page
432
                        [fields] => Array
433
                            (
434
                                ...
435
                            )
436
                    )
437
                [2] => Array
438
                    (
439
                        [name] => HomePage
440
                        [section] => main
441
                        [template] => Home page
442
                        [fields] => Array
443
                            (
444
                                ...
445
                            )
446
                    )
447
            )
448
        */
449
450
        // Add some random values in the field array, so that this values can be uses as test values
451
        foreach ($this->fields as $fkey => $fieldSet) {
452
            foreach ($fieldSet as $key => $values) {
453
                switch ($key) {
454
                    case 'multi_line':
455 View Code Duplication
                    case 'single_line':
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
456
                        $values[0]['random1'] = Lorem::word();
457
                        $values[0]['random2'] = Lorem::word();
458
                        $values[0]['lName'] = $this->labelCase($values[0]['fieldName']);
459
460
                        break;
461 View Code Duplication
                    case 'rich_text':
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
462
                        $values[0]['random1'] = Lorem::sentence();
463
                        $values[0]['random2'] = Lorem::sentence();
464
                        $values[0]['lName'] = $this->labelCase($values[0]['fieldName']);
465
466
                        break;
467
                    case 'link':
468
                        $values['url']['random1'] = 'http://www.' . strtolower(Lorem::word()) . '.com';
469
                        $values['url']['random2'] = 'http://www.' . strtolower(Lorem::word()) . '.com';
470
                        $values['url']['lName'] = $this->labelCase($values['url']['fieldName']);
471
                        $values['text']['random1'] = Lorem::word();
472
                        $values['text']['random2'] = Lorem::word();
473
                        $values['text']['lName'] = $this->labelCase($values['text']['fieldName']);
474
                        $values['new_window']['lName'] = $this->labelCase($values['new_window']['fieldName']);
475
476
                        break;
477
                    case 'image':
478
                        if (count($images) > 0) {
479
                            if (count($images) > 1) {
480
                                $values['image']['id_random1'] = $images[0]->getId();
481
                                $values['image']['url_random1'] = $images[0]->getUrl();
482
                                $values['image']['id_random2'] = $images[1]->getId();
483
                                $values['image']['url_random2'] = $images[1]->getUrl();
484
                            } else {
485
                                $values['image']['id_random1'] = $values['image']['id_random2'] = $images[0]->getId();
486
                                $values['image']['url_random1'] = $values['image']['url_random2'] = $images[0]->getUrl(
487
                                );
488
                            }
489
                        } else {
490
                            $values['image']['id_random1'] = $values['image']['id_random2'] = '1';
491
                            $values['image']['url_random1'] = $values['image']['url_random2'] = 'XXX';
492
                        }
493
                        $values['image']['lName'] = $this->labelCase($values['image']['fieldName']);
494
                        $values['alt_text']['random1'] = Lorem::word();
495
                        $values['alt_text']['random2'] = Lorem::word();
496
                        $values['alt_text']['lName'] = $this->labelCase($values['alt_text']['fieldName']);
497
498
                        break;
499
                    case 'boolean':
500
                        $values[0]['lName'] = $this->labelCase($values[0]['fieldName']);
501
502
                        break;
503 View Code Duplication
                    case 'integer':
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
504
                        $values[0]['random1'] = Base::randomNumber(3000, 99999);
505
                        $values[0]['random2'] = Base::randomNumber(3000, 99999);
506
                        $values[0]['lName'] = $this->labelCase($values[0]['fieldName']);
507
508
                        break;
509 View Code Duplication
                    case 'decimal':
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
510
                        $values[0]['random1'] = Base::randomFloat(2, 0, 99999);
511
                        $values[0]['random2'] = Base::randomFloat(2, 0, 99999);
512
                        $values[0]['lName'] = $this->labelCase($values[0]['fieldName']);
513
514
                        break;
515
                    case 'datetime':
516
                        $values[0]['date_random1'] = DateTime::date('d/m/Y');
517
                        $values[0]['date_random2'] = DateTime::date('d/m/Y');
518
                        $values[0]['time_random1'] = DateTime::time('H:i');
519
                        $values[0]['time_random2'] = DateTime::time('H:i');
520
                        $dparts = explode('/', $values[0]['date_random1']);
521
                        $values[0]['datetime_random1'] = $dparts[2] . '-' . $dparts[1] . '-' . $dparts[0] . ' ' . $values[0]['time_random1'] . ':00';
522
                        $dparts = explode('/', $values[0]['date_random2']);
523
                        $values[0]['datetime_random2'] = $dparts[2] . '-' . $dparts[1] . '-' . $dparts[0] . ' ' . $values[0]['time_random2'] . ':00';
524
                        $values[0]['lName'] = $this->labelCase($values[0]['fieldName']);
525
526
                        break;
527
                }
528
529
                $this->fields[$fkey][$key] = $values;
530
            }
531
        }
532
533
        $params = array(
534
            'name' => $this->entity,
535
            'pages' => $pages,
536
            'fields' => $this->fields,
537
        );
538
        $this->renderFile(
539
            '/Features/PagePart.feature',
540
            $this->bundle->getPath() . '/Features/Admin' . $this->entity . '.feature',
541
            $params
542
        );
543
544
        $this->assistant->writeLine('Generating behat test : <info>OK</info>');
545
    }
546
547
    /**
548
     * Camel case string to space delimited string that will be used for form labels.
549
     *
550
     * @param string $text
551
     *
552
     * @return string
553
     */
554
    private function labelCase($text)
555
    {
556
        return ucfirst(str_replace('_', ' ', Container::underscore($text)));
557
    }
558
}
559