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