Completed
Pull Request — 5.6 (#2830)
by Jeroen
14:14
created

Command/KunstmaanGenerateCommand.php (1 issue)

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\Command;
4
5
use Kunstmaan\AdminBundle\Form\WysiwygType;
6
use Kunstmaan\GeneratorBundle\Helper\CommandAssistant;
7
use Kunstmaan\GeneratorBundle\Helper\GeneratorUtils;
8
use Kunstmaan\GeneratorBundle\Helper\Sf4AppBundle;
9
use Kunstmaan\MediaBundle\Form\Type\MediaType;
10
use Kunstmaan\NodeBundle\Form\Type\URLChooserType;
11
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCommand;
12
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\DependencyInjection\Container;
16
use Symfony\Component\Finder\Finder;
17
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
18
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
19
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
20
use Symfony\Component\Form\Extension\Core\Type\NumberType;
21
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
22
use Symfony\Component\Form\Extension\Core\Type\TextType;
23
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
24
use Symfony\Component\HttpKernel\Kernel;
25
use Symfony\Component\Yaml\Exception\ParseException;
26
use Symfony\Component\Yaml\Yaml;
27
28
abstract class KunstmaanGenerateCommand extends GenerateDoctrineCommand
29
{
30
    /**
31
     * @var CommandAssistant
32
     */
33
    protected $assistant;
34
35
    /**
36
     * Interacts with the user.
37
     *
38
     * @param InputInterface  $input  An InputInterface instance
39
     * @param OutputInterface $output An OutputInterface instance
40
     */
41
    protected function interact(InputInterface $input, OutputInterface $output)
42
    {
43
        $this->setInputAndOutput($input, $output);
44
45
        $welcomeText = $this->getWelcomeText();
46
        if (!empty($welcomeText)) {
47
            $this->assistant->writeSection($this->getWelcomeText());
48
        }
49
50
        $this->doInteract();
51
    }
52
53
    /**
54
     * @return int|null
55
     */
56
    protected function execute(InputInterface $input, OutputInterface $output)
57
    {
58
        $this->setInputAndOutput($input, $output);
59
60
        return $this->doExecute();
61
    }
62
63
    /**
64
     * Create the CommandAssistant.
65
     */
66 View Code Duplication
    private function setInputAndOutput(InputInterface $input, OutputInterface $output)
67
    {
68
        if (is_null($this->assistant)) {
69
            $this->assistant = new CommandAssistant();
70
            $this->assistant->setQuestionHelper($this->getQuestionHelper());
71
            $this->assistant->setKernel($this->getApplication()->getKernel());
72
        }
73
        $this->assistant->setOutput($output);
74
        $this->assistant->setInput($input);
75
    }
76
77
    /**
78
     * Do the interaction with the end user.
79
     */
80
    abstract protected function doInteract();
81
82
    /**
83
     * This function implements the final execution of the Generator.
84
     * It calls the execute function with the correct parameters.
85
     */
86
    abstract protected function doExecute();
87
88
    /**
89
     * The text to be displayed on top of the generator.
90
     *
91
     * @return string|array
92
     */
93
    abstract protected function getWelcomeText();
94
95
    /**
96
     * Get an array with all the bundles the user has created.
97
     *
98
     * @return array
99
     */
100
    protected function getOwnBundles()
101
    {
102
        $bundles = [];
103
        $counter = 1;
104
        $dir = dirname($this->getContainer()->getParameter('kernel.root_dir') . '/') . '/src/';
105
        $finder = new Finder();
106
        $finder->in($dir)->name('*Bundle.php');
107
108
        foreach ($finder as $file) {
109
            $bundles[$counter++] = [
110
                'name' => basename($file->getFilename(), '.php'),
111
                'namespace' => $file->getRelativePath(),
112
                'dir' => $file->getPath(),
113
            ];
114
        }
115
116
        return $bundles;
117
    }
118
119
    /**
120
     * Check that a bundle is available (loaded in AppKernel)
121
     *
122
     * @param string $bundleName
123
     *
124
     * @return bool
125
     */
126
    protected function isBundleAvailable($bundleName)
127
    {
128
        $allBundles = array_keys($this->assistant->getKernel()->getBundles());
129
130
        return in_array($bundleName, $allBundles);
131
    }
132
133
    /**
134
     * Asks for the prefix and sets it on the InputInterface as the 'prefix' option, if this option is not set yet.
135
     * Will set the default to a snake_cased namespace when the namespace has been set on the InputInterface.
136
     *
137
     * @param array  $text      What you want printed before the prefix is asked. If null is provided it'll write a default text.
138
     * @param string $namespace An optional namespace. If this is set it'll create the default based on this prefix.
139
     *                          If it's not provided it'll check if the InputInterface already has the namespace option.
140
     *
141
     * @return string The prefix. But it's also been set on the InputInterface.
142
     */
143
    protected function askForPrefix(array $text = null, $namespace = null)
144
    {
145
        $prefix = $this->assistant->getOptionOrDefault('prefix', null);
146
147
        if (is_null($text)) {
148
            $text = [
149
                'You can add a prefix to the table names of the generated entities for example: ' .
150
                '<comment>projectname_bundlename_</comment>',
151
                'Enter an underscore \'_\' if you don\'t want a prefix.',
152
                '',
153
            ];
154
        }
155
156
        while (is_null($prefix)) {
157
            if (count($text) > 0) {
158
                $this->assistant->writeLine($text);
159
            }
160
161
            if (is_null($namespace) || empty($namespace)) {
162
                $namespace = $this->assistant->getOption('namespace');
163
            } else {
164
                $namespace = $this->fixNamespace($namespace);
165
            }
166
            $defaultPrefix = GeneratorUtils::cleanPrefix($this->convertNamespaceToSnakeCase($namespace));
167
            $prefix = GeneratorUtils::cleanPrefix($this->assistant->ask('Tablename prefix', $defaultPrefix));
168
169
            if ($prefix == '') {
170
                break;
171
            }
172
173
            $output = $this->assistant->getOutput();
174 View Code Duplication
            if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $prefix)) {
175
                $output->writeln(sprintf('<bg=red> "%s" contains invalid characters</>', $prefix));
176
                $prefix = $text = null;
177
178
                continue;
179
            }
180
181
            $this->assistant->setOption('prefix', $prefix);
182
        }
183
184
        return $prefix;
185
    }
186
187
    /**
188
     * Converts something like Namespace\BundleNameBundle to namespace_bundlenamebundle.
189
     *
190
     * @param string $namespace
191
     *
192
     * @return string
193
     */
194 View Code Duplication
    private function convertNamespaceToSnakeCase($namespace)
195
    {
196
        if (is_null($namespace)) {
197
            return null;
198
        }
199
200
        return str_replace('/', '_', strtolower($this->fixNamespace($namespace)));
201
    }
202
203
    /**
204
     * Replaces '\' with '/'.
205
     *
206
     * @param $namespace
207
     *
208
     * @return mixed
209
     */
210
    private function fixNamespace($namespace)
211
    {
212
        return str_replace('\\', '/', $namespace);
213
    }
214
215
    /**
216
     * Ask for which bundle we need to generate something. It there is only one custom bundle
217
     * created by the user, we don't ask anything and just use that bundle. If the user provided
218
     * a namespace as input option, we try to get that bundle first.
219
     *
220
     * @param string      $objectName          The thing we are going to create (pagepart, bundle, layout, ...)
221
     * @param string|null $namespace           The namespace provided as input option
222
     * @param string      $questionMoreBundles
223
     * @param string      $questionOneBundle
224
     *
225
     * @return BundleInterface
226
     */
227
    protected function askForBundleName(
228
        $objectName,
229
        $namespace = null,
230
        $questionMoreBundles = "\nIn which bundle do you want to create the %s",
231
        $questionOneBundle = "The %s will be created for the <comment>%s</comment> bundle.\n"
232
    ) {
233
        if (Kernel::VERSION_ID >= 40000) {
234
            return new Sf4AppBundle($this->getContainer()->getParameter('kernel.project_dir'));
235
        }
236
237
        $ownBundles = $this->getOwnBundles();
238
        if (count($ownBundles) <= 0) {
239
            $this->assistant->writeError("Looks like you don't have created any bundles for your project...", true);
240
        }
241
242
        // If the user provided the namespace as input option
243
        if (!is_null($namespace)) {
244
            foreach ($ownBundles as $key => $bundleInfo) {
245
                if (GeneratorUtils::fixNamespace($namespace) == GeneratorUtils::fixNamespace(
246
                        $bundleInfo['namespace']
247
                    )
248
                ) {
249
                    $bundleName = $bundleInfo['name'];
250
251
                    break;
252
                }
253
            }
254
255
            // When the provided namespace was not found, we show an error on the screen and ask the bundle again
256
            if (empty($bundleName)) {
257
                $this->assistant->writeError("The provided bundle namespace '$namespace' was not found...");
258
            }
259
        }
260
261
        if (empty($bundleName)) {
262
            // If we only have 1 bundle, we don't need to ask
263
            if (count($ownBundles) > 1) {
264
                $bundleSelect = [];
265
                foreach ($ownBundles as $key => $bundleInfo) {
266
                    $bundleSelect[$key] = $bundleInfo['name'];
267
                }
268
                $bundleId = $this->assistant->askSelect(
269
                    sprintf($questionMoreBundles, $objectName),
270
                    $bundleSelect
271
                );
272
                $bundleName = $ownBundles[$bundleId]['name'];
273
274
                $this->assistant->writeLine('');
275
            } else {
276
                $bundleName = $ownBundles[1]['name'];
277
                $this->assistant->writeLine(
278
                    [sprintf($questionOneBundle, $objectName, $bundleName)]
279
                );
280
            }
281
        }
282
283
        $bundle = $this->assistant->getKernel()->getBundle($bundleName);
284
285
        return $bundle;
286
    }
287
288
    /**
289
     * Ask the end user to select one (or more) section configuration(s).
290
     *
291
     * @param string      $question
292
     * @param bool        $multiple
293
     * @param string|null $context
294
     * @param array       $defaultSections
295
     *
296
     * @return array|null
297
     */
298
    protected function askForSections(
299
        $question,
300
        BundleInterface $bundle,
301
        $multiple = false,
302
        $context = null,
303
        $defaultSections = []
304
    ) {
305
        $allSections = $this->getAvailableSections($bundle, $context, $defaultSections);
306
        $sections = [];
307
308
        // If there are more options to choose from, we ask the end user
309
        if (count($allSections) > 0) {
310
            $sectionSelect = [];
311
            foreach ($allSections as $key => $sectionInfo) {
312
                $sectionSelect[$key] = $sectionInfo['name'] . ' (' . $sectionInfo['file'] . ')';
313
            }
314
            $this->assistant->writeLine('');
315
            $sectionIds = $this->assistant->askSelect($question, $sectionSelect, null, $multiple);
316
            if (is_array($sectionIds)) {
317
                foreach ($sectionIds as $id) {
318
                    $sections[] = $allSections[$id]['file'];
319
                }
320
            } else {
321
                $sections[] = $allSections[$sectionIds]['file'];
322
            }
323
        }
324
325
        if ($multiple) {
326
            return $sections;
327
        } else {
328
            return count($sections) > 0 ? $sections[0] : null;
329
        }
330
    }
331
332
    /**
333
     * Get an array with the available page sections. We also parse the yaml files to get more information about
334
     * the sections.
335
     *
336
     * @param BundleInterface $bundle          The bundle for which we want to get the section configuration
337
     * @param string|null     $context         If provided, only return configurations with this context
338
     * @param array           $defaultSections The default section configurations that are always available
339
     *
340
     * @return array
341
     */
342
    protected function getAvailableSections(BundleInterface $bundle, $context = null, $defaultSections = [])
343
    {
344
        $configs = [];
345
        $counter = 1;
346
347
        // Get the available sections from disc
348
        $dir = Kernel::VERSION_ID >= 40000 ?
349
            $this->getContainer()->getParameter('kernel.project_dir') . '/config/kunstmaancms/pageparts/' :
350
            $bundle->getPath() . '/Resources/config/pageparts/'
351
        ;
352
        if (file_exists($dir) && is_dir($dir)) {
353
            $finder = new Finder();
354
            $finder->files()->in($dir)->depth('== 0');
355
            foreach ($finder as $file) {
356
                $info = $this->getSectionInfo($dir, $file->getFileName());
357
358
                if (is_array($info) && (is_null($context) || $info['context'] == $context)) {
359
                    $configs[$counter++] = $info;
360
                    if (array_key_exists($info['file'], $defaultSections)) {
361
                        unset($defaultSections[$info['file']]);
362
                    }
363
                }
364
            }
365
        }
366
367
        // Add the default sections
368
        foreach ($defaultSections as $file => $info) {
369
            if (is_null($context) || $info['context'] == $context) {
370
                $configs[$counter++] = $info;
371
            }
372
        }
373
374
        return $configs;
375
    }
376
377
    /**
378
     * Get the information about a pagepart section configuration file.
379
     *
380
     * @param string $dir
381
     * @param string $file
382
     *
383
     * @return array|null
384
     */
385
    private function getSectionInfo($dir, $file)
386
    {
387
        $info = null;
388
389
        try {
390
            $data = Yaml::parse(file_get_contents($dir . $file));
391
392 View Code Duplication
            if (array_key_exists('kunstmaan_page_part', $data)) {
393
                //Get rid of the bundle config lines
394
                $data = array_values(array_values(array_values($data)[0])[0])[0];
395
            }
396
397
            $info = [
398
                'name' => $data['name'],
399
                'context' => $data['context'],
400
                'file' => $file,
401
                //'file_clean' => substr($file, 0, strlen($file)-4)
402
            ];
403
        } catch (ParseException $e) {
404
        }
405
406
        return $info;
407
    }
408
409
    /**
410
     * Get an array of fields that need to be added to the entity.
411
     *
412
     * @return array
413
     */
414
    protected function askEntityFields(BundleInterface $bundle, array $reservedFields = ['id'])
415
    {
416
        $this->assistant->writeLine('<info>Available field types:</info> ');
417
        $typeSelect = $this->getTypes(true);
418
        foreach ($typeSelect as $type) {
419
            $this->assistant->writeLine(sprintf('<comment>- %s</comment>', $type));
420
        }
421
422
        $fields = [];
423
        $typeStrings = $this->getTypes();
424
        $mediaTypeSelect = $this->getMediaTypes();
425
        $generator = $this->getGenerator();
426
        $container = $this->getContainer();
427
428
        while (true) {
429
            $this->assistant->writeLine('');
430
431
            $fieldName = $this->assistant->askAndValidate(
432
                'New field name (press <return> to stop adding fields)',
433
                function ($name) use ($fields, $reservedFields, $generator) {
434
                    // The fields cannot exist in the reserved field list
435
                    if (in_array($name, $reservedFields)) {
436
                        throw new \InvalidArgumentException(sprintf('Field "%s" is already defined in the parent class', $name));
437
                    }
438
439
                    // The fields cannot exist already
440
                    if (isset($fields[$name])) {
441
                        throw new \InvalidArgumentException(sprintf('Field "%s" is already defined', $name));
442
                    }
443
444
                    // Check reserved words
445
                    if ($generator->isReservedKeyword($name)) {
446
                        throw new \InvalidArgumentException(sprintf('Name "%s" is a reserved word', $name));
447
                    }
448
449
                    // Only accept a-z
450
                    if (!preg_match('/^[a-zA-Z][a-zA-Z_0-9]+$/', $name) && $name != '') {
451
                        throw new \InvalidArgumentException(sprintf('Name "%s" is invalid', $name));
452
                    }
453
454
                    return $name;
455
                }
456
            );
457
458
            // When <return> is entered
459
            if (!$fieldName) {
460
                break;
461
            }
462
463
            $typeId = $this->assistant->askSelect('Field type', $typeSelect);
464
465
            // If single -or multipe entity reference in chosen, we need to ask for the entity name
466
            if (in_array($typeStrings[$typeId], ['single_ref', 'multi_ref'])) {
467
                $bundleName = $bundle->getName();
468
                $egName = $this->isSymfony4() ? 'App\Entity\FaqItem' : "$bundleName:FaqItem, $bundleName:Blog/Comment";
469
                $question = sprintf('Reference entity name (eg. %s)', $egName);
470
                $name = $this->assistant->askAndValidate(
471
                    $question,
472
                    function ($name) use ($generator, $container) {
473
                        /*
474
                         * Replace slash to backslash. Eg: CmsBundle:Blog/Comment --> CmsBundle:Blog\Comment
475
                         *
476
                         * @see \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory::getMetadataFor()
477
                         * @see \Doctrine\ORM\Mapping\ClassMetadataFactory::getFqcnFromAlias()
478
                         */
479
                        if (!$this->isSymfony4()) {
480
                            $name = strtr($name, '/', '\\');
481
482
                            $parts = explode(':', $name);
483
484
                            // Should contain colon
485
                            if (count($parts) != 2) {
486
                                throw new \InvalidArgumentException(sprintf('"%s" is an invalid entity name', $name));
487
                            }
488
                        } else {
489
                            $parts = explode('\\', $name);
490
                        }
491
492
                        // Check reserved words
493
                        if ($generator->isReservedKeyword(end($parts))) {
494
                            throw new \InvalidArgumentException(sprintf('"%s" contains a reserved word', $name));
495
                        }
496
497
                        $em = $container->get('doctrine')->getManager();
498
499
                        try {
500
                            $em->getClassMetadata($name);
501
                        } catch (\Exception $e) {
502
                            throw new \InvalidArgumentException(sprintf('Entity "%s" not found', $name));
503
                        }
504
505
                        return $name;
506
                    },
507
                    null,
508
                    [$bundleName]
509
                );
510
511
                $extra = $name;
512
            } else {
513
                $extra = null;
514
            }
515
516
            // If image type, force image media filter
517
            if ($typeStrings[$typeId] == 'image') {
518
                $extra = 'image';
519
            }
520
521
            // If media type, ask for media filter
522
            if ($typeStrings[$typeId] == 'media') {
523
                $mediaTypeId = $this->assistant->askSelect('Media filter', $mediaTypeSelect);
524
                $extra = strtolower($mediaTypeSelect[$mediaTypeId]);
525
            }
526
527
            if ($typeStrings[$typeId] == 'image' || $typeStrings[$typeId] == 'media') {
528
                // Ask the allowed mimetypes for the media ojbect
529
                $mimeTypes = $this->assistant->ask('Do you want to limit the possible file types? Then specify a comma-seperated list of types (example: image/png,image/svg+xml), otherwise press ENTER',
530
                    null
531
                );
532
                if (isset($mimeTypes)) {
533
                    $mimeTypes = explode(',', $mimeTypes);
534
                }
535
                $data = [
536
                    'name' => $fieldName,
537
                    'type' => $typeStrings[$typeId],
538
                    'extra' => $extra,
539
                    'mimeTypes' => $mimeTypes,
540
                    'minHeight' => null,
541
                    'maxHeight' => null,
542
                    'minWidth' => null,
543
                    'maxWidth' => null,
544
                ];
545
546
                if ($extra == 'image') {
547
                    $minHeight = $maxHeight = $minWidth = $maxWidth = null;
548
                    if ($this->assistant->askConfirmation('Do you want to add validation of the dimensions of the media object? (y/n)',
549
                        'n',
550
                        '?',
551
                        false
552
                    )) {
553
                        // Ask the minimum height allowed for the image
554
                        $lengthValidation = function ($length) {
555
                            if ((is_numeric($length) && $length < 0) || (!is_numeric($length) && !empty($length))) {
556
                                throw new \InvalidArgumentException(sprintf('"%s" is not a valid length', $length));
557
                            } else {
558
                                return $length;
559
                            }
560
                        };
561
562
                        $minHeight = $this->assistant->askAndValidate('What is the minimum height for the media object? (in pixels)',
563
                            $lengthValidation
564
                        );
565
566
                        // Ask the maximum height allowed for the image
567
                        $maxHeight = $this->assistant->askAndValidate('What is the maximum height for the media object? (in pixels)',
568
                            $lengthValidation
569
                        );
570
571
                        // Ask the minimum width allowed for the image
572
                        $minWidth = $this->assistant->askAndValidate('What is the minimum width for the media object? (in pixels)',
573
                            $lengthValidation
574
                        );
575
576
                        //Ask the maximum width allowed for the image
577
                        $maxWidth = $this->assistant->askAndValidate('What is the maximum width for the media object? (in pixels)',
578
                            $lengthValidation
579
                        );
580
                    }
581
                    $data = [
582
                        'name' => $fieldName,
583
                        'type' => 'image',
584
                        'extra' => $extra,
585
                        'minHeight' => $minHeight,
586
                        'maxHeight' => $maxHeight,
587
                        'minWidth' => $minWidth,
588
                        'maxWidth' => $maxWidth,
589
                        'mimeTypes' => $mimeTypes,
590
                    ];
591
                }
592
            } else {
593
                $data = [
594
                    'name' => $fieldName,
595
                    'type' => $typeStrings[$typeId],
596
                    'extra' => $extra,
597
                    'minHeight' => null,
598
                    'maxHeight' => null,
599
                    'minWidth' => null,
600
                    'maxWidth' => null,
601
                    'mimeTypes' => null,
602
                ];
603
            }
604
605
            $fields[$fieldName] = $data;
606
        }
607
608
        return $fields;
609
    }
610
611
    /**
612
     * Get all the available types.
613
     *
614
     * @param bool $niceNames
615
     *
616
     * @return array
617
     */
618
    private function getTypes($niceNames = false)
619
    {
620
        $counter = 1;
621
622
        $types = [];
623
        $types[$counter++] = $niceNames ? 'Single line text' : 'single_line';
624
        $types[$counter++] = $niceNames ? 'Multi line text' : 'multi_line';
625
        $types[$counter++] = $niceNames ? 'Wysiwyg' : 'wysiwyg';
626
        $types[$counter++] = $niceNames ? 'Link (url, text, new window)' : 'link';
627
        if ($this->isBundleAvailable('KunstmaanMediaPagePartBundle')) {
628
            $types[$counter++] = $niceNames ? 'Image (media, alt text)' : 'image';
629
            $types[$counter++] = $niceNames ? 'Media (File or Video or Slideshow)' : 'media';
630
        }
631
        $types[$counter++] = $niceNames ? 'Single entity reference' : 'single_ref';
632
        $types[$counter++] = $niceNames ? 'Multi entity reference' : 'multi_ref';
633
        $types[$counter++] = $niceNames ? 'Boolean' : 'boolean';
634
        $types[$counter++] = $niceNames ? 'Integer' : 'integer';
635
        $types[$counter++] = $niceNames ? 'Decimal number' : 'decimal';
636
        $types[$counter++] = $niceNames ? 'DateTime' : 'datetime';
637
638
        return $types;
639
    }
640
641
    /**
642
     * Get all available media types.
643
     *
644
     * @return array
645
     */
646
    private function getMediaTypes()
647
    {
648
        $counter = 1;
649
650
        $types = [];
651
        $types[$counter++] = 'None';
652
        $types[$counter++] = 'File';
653
        $types[$counter++] = 'Image';
654
        $types[$counter++] = 'Video';
655
656
        return $types;
657
    }
658
659
    /**
660
     * Get all the entity fields for a specific type.
661
     *
662
     * @param      $objectName
663
     * @param      $prefix
664
     * @param      $name
665
     * @param      $type
666
     * @param null $extra
667
     * @param bool $allNullable
668
     * @param null $minHeight
669
     * @param null $maxHeight
670
     * @param null $minWidth
671
     * @param null $maxWidth
672
     * @param null $mimeTypes
673
     *
674
     * @return array
675
     */
676
    protected function getEntityFields(
677
        BundleInterface $bundle,
678
        $objectName,
679
        $prefix,
680
        $name,
681
        $type,
682
        $extra = null,
683
        $allNullable = false,
684
        $minHeight = null,
685
        $maxHeight = null,
686
        $minWidth = null,
687
        $maxWidth = null,
688
        $mimeTypes = null
689
    ) {
690
        $fields = [];
691
        switch ($type) {
692 View Code Duplication
            case 'single_line':
693
                $fields[$type][] = [
694
                    'fieldName' => lcfirst(Container::camelize($name)),
695
                    'type' => 'string',
696
                    'length' => '255',
697
                    'formType' => TextType::class,
698
                    'nullable' => $allNullable,
699
                ];
700
701
                break;
702 View Code Duplication
            case 'multi_line':
703
                $fields[$type][] = [
704
                    'fieldName' => lcfirst(Container::camelize($name)),
705
                    'type' => 'text',
706
                    'formType' => TextareaType::class,
707
                    'nullable' => $allNullable,
708
                ];
709
710
                break;
711 View Code Duplication
            case 'wysiwyg':
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...
712
                $fields[$type][] = [
713
                    'fieldName' => lcfirst(Container::camelize($name)),
714
                    'type' => 'text',
715
                    'formType' => WysiwygType::class,
716
                    'nullable' => $allNullable,
717
                ];
718
719
                break;
720
            case 'link':
721
                foreach (['url', 'text'] as $subField) {
722
                    $fields[$type][$subField] = [
723
                        'fieldName' => lcfirst(Container::camelize($name . '_' . $subField)),
724
                        'type' => 'string',
725
                        'formType' => $subField == 'url' ? URLChooserType::class : TextType::class,
726
                        'nullable' => $allNullable,
727
                    ];
728
                }
729
                $fields[$type]['new_window'] = [
730
                    'fieldName' => lcfirst(Container::camelize($name . '_new_window')),
731
                    'type' => 'boolean',
732
                    'nullable' => true,
733
                    'formType' => CheckboxType::class,
734
                ];
735
736
                break;
737
            case 'image':
738
                $fields[$type]['image'] = [
739
                    'fieldName' => lcfirst(Container::camelize($name)),
740
                    'type' => 'image',
741
                    'formType' => MediaType::class,
742
                    'mediaType' => $extra,
743
                    'minHeight' => $minHeight,
744
                    'maxHeight' => $maxHeight,
745
                    'minWidth' => $minWidth,
746
                    'maxWidth' => $maxWidth,
747
                    'mimeTypes' => $mimeTypes,
748
                    'targetEntity' => 'Kunstmaan\MediaBundle\Entity\Media',
749
                    'joinColumn' => [
750
                        'name' => str_replace('.', '_', Container::underscore($name . '_id')),
751
                        'referencedColumnName' => 'id',
752
                    ],
753
                    'nullable' => $allNullable,
754
                ];
755
                $fields[$type]['alt_text'] = [
756
                    'fieldName' => lcfirst(Container::camelize($name . '_alt_text')),
757
                    'type' => 'text',
758
                    'nullable' => true,
759
                    'formType' => TextType::class,
760
                ];
761
762
                break;
763
            case 'media':
764
                $fields[$type][] = [
765
                    'fieldName' => lcfirst(Container::camelize($name)),
766
                    'type' => 'media',
767
                    'formType' => MediaType::class,
768
                    'mediaType' => $extra,
769
                    'mimeTypes' => $mimeTypes,
770
                    'targetEntity' => 'Kunstmaan\MediaBundle\Entity\Media',
771
                    'joinColumn' => [
772
                        'name' => str_replace('.', '_', Container::underscore($name . '_id')),
773
                        'referencedColumnName' => 'id',
774
                    ],
775
                    'nullable' => $allNullable,
776
                ];
777
778
                break;
779
            case 'single_ref':
780
                $em = $this->getContainer()->get('doctrine')->getManager();
781
                $entityName = $em->getClassMetadata($extra)->getName();
782
                $fields[$type][] = [
783
                    'fieldName' => lcfirst(Container::camelize($name)),
784
                    'type' => 'entity',
785
                    'formType' => EntityType::class,
786
                    'targetEntity' => $entityName,
787
                    'joinColumn' => [
788
                        'name' => str_replace('.', '_', Container::underscore($name . '_id')),
789
                        'referencedColumnName' => 'id',
790
                    ],
791
                    'nullable' => $allNullable,
792
                ];
793
794
                break;
795
            case 'multi_ref':
796
                $em = $this->getContainer()->get('doctrine')->getManager();
797
                $entityName = $em->getClassMetadata($extra)->getName();
798
                $parts = explode('\\', $entityName);
799
                $joinTableName = strtolower(
800
                    $prefix . Container::underscore($objectName) . '_' . Container::underscore(
801
                        $parts[count($parts) - 1]
802
                    )
803
                );
804
                $fields[$type][] = [
805
                    'fieldName' => lcfirst(Container::camelize($name)),
806
                    'type' => 'entity',
807
                    'formType' => EntityType::class,
808
                    'targetEntity' => $entityName,
809
                    'joinTable' => [
810
                        'name' => $joinTableName,
811
                        'joinColumns' => [
812
                            [
813
                                'name' => strtolower(Container::underscore($objectName)) . '_id',
814
                                'referencedColumnName' => 'id',
815
                            ],
816
                        ],
817
                        'inverseJoinColumns' => [
818
                            [
819
                                'name' => strtolower(
820
                                        Container::underscore($parts[count($parts) - 1])
821
                                    ) . '_id',
822
                                'referencedColumnName' => 'id',
823
                                'unique' => true,
824
                            ],
825
                        ],
826
                    ],
827
                    'nullable' => $allNullable,
828
                ];
829
830
                break;
831 View Code Duplication
            case 'boolean':
832
                $fields[$type][] = [
833
                    'fieldName' => lcfirst(Container::camelize($name)),
834
                    'type' => 'boolean',
835
                    'formType' => CheckboxType::class,
836
                    'nullable' => $allNullable,
837
                ];
838
839
                break;
840 View Code Duplication
            case 'integer':
841
                $fields[$type][] = [
842
                    'fieldName' => lcfirst(Container::camelize($name)),
843
                    'type' => 'integer',
844
                    'formType' => IntegerType::class,
845
                    'nullable' => $allNullable,
846
                ];
847
848
                break;
849 View Code Duplication
            case 'decimal':
850
                $fields[$type][] = [
851
                    'fieldName' => lcfirst(Container::camelize($name)),
852
                    'type' => 'decimal',
853
                    'precision' => 10,
854
                    'scale' => 2,
855
                    'formType' => NumberType::class,
856
                    'nullable' => $allNullable,
857
                ];
858
859
                break;
860 View Code Duplication
            case 'datetime':
861
                $fields[$type][] = [
862
                    'fieldName' => lcfirst(Container::camelize($name)),
863
                    'type' => 'datetime',
864
                    'formType' => DateTimeType::class,
865
                    'nullable' => $allNullable,
866
                ];
867
868
                break;
869
        }
870
871
        return $fields;
872
    }
873
874
    /**
875
     * Get an array with the available page templates.
876
     *
877
     * @param BundleInterface $bundle The bundle for which we want to get the template configurations
878
     *
879
     * @return array
880
     */
881
    protected function getAvailableTemplates(BundleInterface $bundle)
882
    {
883
        $configs = [];
884
        $counter = 1;
885
886
        // Get the available sections from disc
887
        if (Kernel::VERSION_ID >= 40000) {
888
            $dir = $this->getContainer()->getParameter('kernel.project_dir') . '/config/kunstmaancms/pagetemplates/';
889
        } else {
890
            $dir = $bundle->getPath() . '/Resources/config/pagetemplates/';
891
        }
892
893
        if (file_exists($dir) && is_dir($dir)) {
894
            $finder = new Finder();
895
            $finder->files()->in($dir)->depth('== 0');
896
            foreach ($finder as $file) {
897
                $info = $this->getTemplateInfo($dir, $file->getFileName());
898
                if (is_array($info)) {
899
                    $configs[$counter++] = $info;
900
                }
901
            }
902
        }
903
904
        return $configs;
905
    }
906
907
    /**
908
     * Get the information about a pagepart section configuration file.
909
     *
910
     * @param string $dir
911
     * @param string $file
912
     *
913
     * @return array|null
914
     */
915
    protected function getTemplateInfo($dir, $file)
916
    {
917
        $info = null;
918
919
        try {
920
            $data = Yaml::parse(file_get_contents($dir . $file));
921
922 View Code Duplication
            if (array_key_exists('kunstmaan_page_part', $data)) {
923
                //Get rid of the bundle config lines
924
                $data = array_values(array_values(array_values($data)[0])[0])[0];
925
            }
926
927
            // Parse contexts
928
            $contexts = [];
929
            foreach ($data['rows'] as $row) {
930
                foreach ($row['regions'] as $region) {
931
                    $contexts[] = $region['name'];
932
                }
933
            }
934
            $info = [
935
                'name' => $data['name'],
936
                'contexts' => $contexts,
937
                'file' => $file,
938
            ];
939
        } catch (ParseException $e) {
940
        }
941
942
        return $info;
943
    }
944
945
    /**
946
     * Get an array with the available page templates.
947
     *
948
     * @param BundleInterface $bundle The bundle for which we want to get the template configurations
949
     *
950
     * @return array
951
     */
952
    protected function getAvailablePages(BundleInterface $bundle)
953
    {
954
        $pages = [];
955
        $counter = 1;
956
957
        // Get the available pages from disc
958
        $dir = $bundle->getPath() . '/Entity/Pages/';
959
        if (file_exists($dir) && is_dir($dir)) {
960
            $finder = new Finder();
961
            $finder->files()->in($dir)->depth('== 0');
962
            foreach ($finder as $file) {
963
                $pages[$counter++] = [
964
                    'name' => substr($file->getFileName(), 0, strlen($file->getFileName()) - 4),
965
                    'path' => $file->getPathName(),
966
                ];
967
            }
968
        }
969
970
        return $pages;
971
    }
972
973
    /**
974
     * Check that it is possible to generate the behat tests.
975
     *
976
     * @return bool
977
     */
978
    protected function canGenerateBehatTests(BundleInterface $bundle)
979
    {
980
        $behatFile = dirname($this->getContainer()->getParameter('kernel.root_dir') . '/') . '/behat.yml';
981
        $pagePartContext = $bundle->getPath() . '/Features/Context/PagePartContext.php';
982
        $behatTestPage = $bundle->getPath() . '/Entity/Pages/BehatTestPage.php';
983
984
        // Make sure behat is configured and the PagePartContext and BehatTestPage exits
985
        return file_exists($behatFile) && file_exists($pagePartContext) && file_exists($behatTestPage);
986
    }
987
988
    /**
989
     * @internal
990
     */
991
    protected function isSymfony4()
992
    {
993
        return Kernel::VERSION_ID >= 40000;
994
    }
995
}
996