MakeFormLayer   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 53
c 2
b 0
f 0
dl 0
loc 99
rs 10
wmc 13

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A configureDependencies() 0 5 1
A getCommandName() 0 3 1
A configureCommand() 0 7 1
A interact() 0 12 2
B generate() 0 44 7
1
<?php
2
3
4
namespace Pfilsx\FormLayer\Maker;
5
6
7
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Pfilsx\FormLayer\Renderer\FormLayerRenderer;
10
use ReflectionClass;
11
use Symfony\Bundle\MakerBundle\ConsoleStyle;
12
use Symfony\Bundle\MakerBundle\DependencyBuilder;
13
use Symfony\Bundle\MakerBundle\Doctrine\DoctrineHelper;
14
use Symfony\Bundle\MakerBundle\Generator;
15
use Symfony\Bundle\MakerBundle\InputConfiguration;
16
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
17
use Symfony\Bundle\MakerBundle\Str;
18
use Symfony\Bundle\MakerBundle\Validator;
19
use Symfony\Component\Console\Command\Command;
20
use Symfony\Component\Console\Input\InputArgument;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Question\Question;
23
24
class MakeFormLayer extends AbstractMaker
25
{
26
    private $entityHelper;
27
    private $formLayerRenderer;
28
29
    public function __construct(DoctrineHelper $entityHelper, FormLayerRenderer $formLayerRenderer)
30
    {
31
        $this->entityHelper = $entityHelper;
32
        $this->formLayerRenderer = $formLayerRenderer;
33
    }
34
35
    public static function getCommandName(): string
36
    {
37
        return 'make:form-layer';
38
    }
39
40
    public function configureCommand(Command $command, InputConfiguration $inputConfig)
41
    {
42
        $command
43
            ->setDescription('Creates a new form layer class')
44
            ->addArgument('name', InputArgument::OPTIONAL, sprintf('The name of the form layer class (e.g. <fg=yellow>%sFormLayer</>)', Str::asClassName(Str::getRandomTerm())))
45
            ->addArgument('bound-class', InputArgument::OPTIONAL, 'The name of Entity or fully qualified model class name that the new form will be bound to (empty for none)');
46
        $inputConfig->setArgumentAsNonInteractive('bound-class');
47
    }
48
49
    public function configureDependencies(DependencyBuilder $dependencies)
50
    {
51
        $dependencies->addClassDependency(
52
            DoctrineBundle::class,
53
            'orm'
54
        );
55
    }
56
57
    /**
58
     * @param InputInterface $input
59
     * @param ConsoleStyle $io
60
     * @param Command $command
61
     *
62
     * @codeCoverageIgnore
63
     */
64
    public function interact(InputInterface $input, ConsoleStyle $io, Command $command)
65
    {
66
        if (null === $input->getArgument('bound-class')) {
67
            $argument = $command->getDefinition()->getArgument('bound-class');
68
            $entities = $this->entityHelper->getEntitiesForAutocomplete();
69
            $question = new Question($argument->getDescription());
70
            $question->setValidator(function ($answer) use ($entities) {
71
                return Validator::existsOrNull($answer, $entities);
72
            });
73
            $question->setAutocompleterValues($entities);
74
            $question->setMaxAttempts(3);
75
            $input->setArgument('bound-class', $io->askQuestion($question));
76
        }
77
    }
78
79
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
80
    {
81
        $formClassNameDetails = $generator->createClassNameDetails(
82
            $input->getArgument('name'),
0 ignored issues
show
Bug introduced by
It seems like $input->getArgument('name') can also be of type null and string[]; however, parameter $name of Symfony\Bundle\MakerBund...reateClassNameDetails() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

82
            /** @scrutinizer ignore-type */ $input->getArgument('name'),
Loading history...
83
            'FormLayer\\',
84
            'FormLayer'
85
        );
86
87
        $formFields = ['form_field'];
88
89
        $boundClass = $input->getArgument('bound-class');
90
        $boundClassDetails = null;
91
        if (null !== $boundClass) {
92
            $formFields = [];
93
            $boundClassDetails = $generator->createClassNameDetails(
94
                $boundClass,
0 ignored issues
show
Bug introduced by
It seems like $boundClass can also be of type string[]; however, parameter $name of Symfony\Bundle\MakerBund...reateClassNameDetails() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

94
                /** @scrutinizer ignore-type */ $boundClass,
Loading history...
95
                'Entity\\'
96
            );
97
            $doctrineMetadata = $this->entityHelper->getMetadata($boundClassDetails->getFullName());
98
            if ($doctrineMetadata instanceof ClassMetadata) {
99
                foreach ($doctrineMetadata->getFieldNames() as $fieldName) {
100
                    $formFields[] = $fieldName;
101
                }
102
                foreach ($doctrineMetadata->associationMappings as $fieldName => $relation) {
103
                    if ($relation['type'] === ClassMetadata::MANY_TO_ONE) {
104
                        $formFields[] = $fieldName;
105
                    }
106
                }
107
            } else {
108
                $reflect = new ReflectionClass($boundClassDetails->getFullName());
109
                foreach ($reflect->getProperties() as $prop) {
110
                    $formFields[] = $prop->getName();
111
                }
112
            }
113
        }
114
115
        $this->formLayerRenderer->render(
116
            $formClassNameDetails,
117
            $formFields,
118
            $boundClassDetails
119
        );
120
        $generator->writeChanges();
121
        $this->writeSuccessMessage($io);
122
        $io->text('Next: Add fields to your form layer and start using it.');
123
    }
124
}
125