MakeGrid::generate()   B
last analyzed

Complexity

Conditions 7
Paths 3

Size

Total Lines 46
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 32
nc 3
nop 3
dl 0
loc 46
rs 8.4746
c 1
b 0
f 0
1
<?php
2
3
4
namespace Pfilsx\DataGrid\Maker;
5
6
7
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use ReflectionClass;
10
use ReflectionException;
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 MakeGrid extends AbstractMaker
25
{
26
27
    private $entityHelper;
28
    private $gridTypeRenderer;
29
30
    public function __construct(DoctrineHelper $entityHelper, GridTypeRenderer $gridTypeRenderer)
31
    {
32
        $this->entityHelper = $entityHelper;
33
        $this->gridTypeRenderer = $gridTypeRenderer;
34
    }
35
36
    /**
37
     * Return the command name for your maker (e.g. make:report).
38
     *
39
     * @return string
40
     */
41
    public static function getCommandName(): string
42
    {
43
        return 'make:grid';
44
    }
45
46
    /**
47
     * Configure the command: set description, input arguments, options, etc.
48
     *
49
     * By default, all arguments will be asked interactively. If you want
50
     * to avoid that, use the $inputConfig->setArgumentAsNonInteractive() method.
51
     *
52
     * @param Command $command
53
     * @param InputConfiguration $inputConfig
54
     */
55
    public function configureCommand(Command $command, InputConfiguration $inputConfig)
56
    {
57
        $command
58
            ->setDescription('Creates a new grid class')
59
            ->addArgument('name', InputArgument::OPTIONAL, sprintf('The name of the grid class (e.g. <fg=yellow>%sGridType</>)', Str::asClassName(Str::getRandomTerm())))
60
            ->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)');
61
//            ->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeForm.txt'));
62
        $inputConfig->setArgumentAsNonInteractive('bound-class');
63
    }
64
65
    /**
66
     * Configure any library dependencies that your maker requires.
67
     *
68
     * @param DependencyBuilder $dependencies
69
     */
70
    public function configureDependencies(DependencyBuilder $dependencies)
71
    {
72
        $dependencies->addClassDependency(
73
            DoctrineBundle::class,
74
            'orm'
75
        );
76
    }
77
78
    public function interact(InputInterface $input, ConsoleStyle $io, Command $command)
79
    {
80
        if (null === $input->getArgument('bound-class')) {
81
            $argument = $command->getDefinition()->getArgument('bound-class');
82
            $entities = $this->entityHelper->getEntitiesForAutocomplete();
83
            $question = new Question($argument->getDescription());
84
            $question->setValidator(function ($answer) use ($entities) {return Validator::existsOrNull($answer, $entities); });
85
            $question->setAutocompleterValues($entities);
86
            $question->setMaxAttempts(3);
87
            $input->setArgument('bound-class', $io->askQuestion($question));
88
        }
89
    }
90
91
    /**
92
     * Called after normal code generation: allows you to do anything.
93
     *
94
     * @param InputInterface $input
95
     * @param ConsoleStyle $io
96
     * @param Generator $generator
97
     * @throws ReflectionException
98
     */
99
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
100
    {
101
        $gridClassNameDetails = $generator->createClassNameDetails(
102
            $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

102
            /** @scrutinizer ignore-type */ $input->getArgument('name'),
Loading history...
103
            'Grid\\',
104
            'Type'
105
        );
106
107
        $gridFieldsWithTypes = ['field_name' => null];
108
109
        $boundClass = $input->getArgument('bound-class');
110
        $boundClassDetails = null;
111
        if (null !== $boundClass) {
112
            $gridFieldsWithTypes = [];
113
            $boundClassDetails = $generator->createClassNameDetails(
114
                $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

114
                /** @scrutinizer ignore-type */ $boundClass,
Loading history...
115
                'Entity\\'
116
            );
117
            $doctrineMetadata = $this->entityHelper->getMetadata($boundClassDetails->getFullName());
118
            if ($doctrineMetadata instanceof ClassMetadata) {
119
                foreach ($doctrineMetadata->getFieldNames() as $fieldName){
120
                    $gridFieldsWithTypes[$fieldName] = $doctrineMetadata->getTypeOfField($fieldName);
121
                }
122
                foreach ($doctrineMetadata->associationMappings as $fieldName => $relation) {
123
                    if ($relation['type'] === ClassMetadata::MANY_TO_ONE) {
124
                        $gridFieldsWithTypes[$fieldName] = 'relation';
125
                    }
126
                }
127
            } else {
128
                $reflect = new ReflectionClass($boundClassDetails->getFullName());
129
                foreach ($reflect->getProperties() as $prop) {
130
                    $gridFieldsWithTypes[$prop->getName()] = null;
131
                }
132
            }
133
        }
134
135
        $this->gridTypeRenderer->render(
136
            $gridClassNameDetails,
137
            $gridFieldsWithTypes,
138
            $boundClassDetails
139
        );
140
        $generator->writeChanges();
141
        $this->writeSuccessMessage($io);
142
        $io->text([
143
            'Next: Add fields to your grid and start using it.',
144
            'Find the documentation at <fg=yellow>https://github.com/pfilsx/DataGridBundle/blob/master/src/Resources/doc</>',
145
        ]);
146
    }
147
}