MakeCrud::generate()   B
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 112
Code Lines 80

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 3 Features 0
Metric Value
cc 2
eloc 80
c 3
b 3
f 0
nc 2
nop 3
dl 0
loc 112
rs 8.4362

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Koff\Bundle\CrudMakerBundle\Maker;
4
5
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
0 ignored issues
show
Bug introduced by
The type Doctrine\Bundle\DoctrineBundle\DoctrineBundle was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Doctrine\Common\Inflector\Inflector;
7
use Doctrine\ORM\EntityManagerInterface;
8
use Doctrine\ORM\Mapping\ClassMetadataInfo;
9
use Doctrine\ORM\Mapping\Column;
10
use Koff\Bundle\CrudMakerBundle\GeneratorHelper;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
0 ignored issues
show
Bug introduced by
The type Sensio\Bundle\FrameworkE...dle\Configuration\Route was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Symfony\Bundle\MakerBundle\ConsoleStyle;
13
use Symfony\Bundle\MakerBundle\DependencyBuilder;
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\TwigBundle\TwigBundle;
0 ignored issues
show
Bug introduced by
The type Symfony\Bundle\TwigBundle\TwigBundle was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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\Form\AbstractType;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Form\AbstractType was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Symfony\Component\Security\Csrf\CsrfTokenManager;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Security\Csrf\CsrfTokenManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use Symfony\Component\Validator\Validation;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Validator\Validation was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
26
/**
27
 * @author Sadicov Vladimir <[email protected]>
28
 */
29
final class MakeCrud extends AbstractMaker
30
{
31
    private $entityManager;
32
33
    public function __construct(EntityManagerInterface $entityManager)
34
    {
35
        $this->entityManager = $entityManager;
36
    }
37
38
    public static function getCommandName(): string
39
    {
40
        return 'make:crud';
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function configureCommand(Command $command, InputConfiguration $inputConfig)
47
    {
48
        $command
49
            ->setDescription('Creates CRUD for Doctrine entity class')
50
            ->addArgument('entity-class', InputArgument::OPTIONAL, sprintf('The class name of the entity to create CRUD (e.g. <fg=yellow>%s</>)', Str::asClassName(Str::getRandomTerm())))
51
            ->setHelp(file_get_contents(__DIR__.'/../Resources/help/MakeCrud.txt'))
52
        ;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58
    public function configureDependencies(DependencyBuilder $dependencies)
59
    {
60
        $dependencies->addClassDependency(
61
            Route::class,
62
            'annotations'
63
        );
64
65
        $dependencies->addClassDependency(
66
            AbstractType::class,
67
            'form'
68
        );
69
70
        $dependencies->addClassDependency(
71
            Validation::class,
72
            'validator'
73
        );
74
75
        $dependencies->addClassDependency(
76
            TwigBundle::class,
77
            'twig-bundle'
78
        );
79
80
        $dependencies->addClassDependency(
81
            DoctrineBundle::class,
82
            'orm'
83
        );
84
85
        $dependencies->addClassDependency(
86
            Column::class,
87
            'orm'
88
        );
89
90
        $dependencies->addClassDependency(
91
            CsrfTokenManager::class,
92
            'security-csrf'
93
        );
94
    }
95
96
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
97
    {
98
        $entityClassNameDetails = $generator->createClassNameDetails(
99
            $input->getArgument('entity-class'),
0 ignored issues
show
Bug introduced by
It seems like $input->getArgument('entity-class') 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

99
            /** @scrutinizer ignore-type */ $input->getArgument('entity-class'),
Loading history...
100
            'Entity\\'
101
        );
102
103
        $controllerClassNameDetails = $generator->createClassNameDetails(
104
            $entityClassNameDetails->getRelativeNameWithoutSuffix(),
105
            'Controller\\',
106
            'Controller'
107
        );
108
109
        $formClassNameDetails = $generator->createClassNameDetails(
110
            $entityClassNameDetails->getRelativeNameWithoutSuffix(),
111
            'Form\\',
112
            'Type'
113
        );
114
115
        $metadata = $this->entityManager->getClassMetadata($entityClassNameDetails->getFullName());
116
        $entityVarPlural = lcfirst(Inflector::pluralize($entityClassNameDetails->getShortName()));
117
        $entityVarSingular = lcfirst(Inflector::singularize($entityClassNameDetails->getShortName()));
118
        $routeName = Str::asRouteName($controllerClassNameDetails->getRelativeNameWithoutSuffix());
119
120
        $path = __DIR__.'/../Resources/skeleton/';
121
122
        $generator->generateClass(
123
            $controllerClassNameDetails->getFullName(),
124
            $path.'controller/Controller.tpl.php',
125
            [
126
                'entity_full_class_name' => $entityClassNameDetails->getFullName(),
127
                'entity_class_name' => $entityClassNameDetails->getShortName(),
128
                'form_full_class_name' => $formClassNameDetails->getFullName(),
129
                'form_class_name' => $formClassNameDetails->getShortName(),
130
                'route_path' => Str::asRoutePath($controllerClassNameDetails->getRelativeNameWithoutSuffix()),
131
                'route_name' => $routeName,
132
                'entity_var_plural' => $entityVarPlural,
133
                'entity_var_singular' => $entityVarSingular,
134
                'entity_identifier' => $metadata->identifier[0],
0 ignored issues
show
Bug introduced by
Accessing identifier on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
135
            ]
136
        );
137
138
        $helper = new GeneratorHelper();
139
140
        $generator->generateClass(
141
            $formClassNameDetails->getFullName(),
142
            $path.'form/Type.tpl.php',
143
            [
144
                'entity_class_exists' => true,
145
                'entity_full_class_name' => $entityClassNameDetails->getFullName(),
146
                'entity_class_name' => $entityClassNameDetails->getShortName(),
147
                'form_fields' => $this->getFormFieldsFromEntity($metadata),
148
            ]
149
        );
150
151
        $baseLayoutExists = true;
152
        $templatesPath = Str::asFilePath($controllerClassNameDetails->getRelativeNameWithoutSuffix());
153
154
        $templates = [
155
            '_delete_form' => [
156
                'route_name' => $routeName,
157
                'entity_identifier' => $metadata->identifier[0],
158
            ],
159
            '_form' => [],
160
            'edit' => [
161
                'helper' => $helper,
162
                'base_layout_exists' => $baseLayoutExists,
163
                'entity_class_name' => $entityClassNameDetails->getShortName(),
164
                'entity_var_singular' => $entityVarSingular,
165
                'entity_identifier' => $metadata->identifier[0],
166
                'route_name' => $routeName,
167
            ],
168
            'index' => [
169
                'helper' => $helper,
170
                'base_layout_exists' => $baseLayoutExists,
171
                'entity_class_name' => $entityClassNameDetails->getShortName(),
172
                'entity_var_plural' => $entityVarPlural,
173
                'entity_var_singular' => $entityVarSingular,
174
                'entity_identifier' => $metadata->identifier[0],
175
                'entity_fields' => $metadata->fieldMappings,
0 ignored issues
show
Bug introduced by
Accessing fieldMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
176
                'route_name' => $routeName,
177
            ],
178
            'new' => [
179
                'helper' => $helper,
180
                'base_layout_exists' => $baseLayoutExists,
181
                'entity_class_name' => $entityClassNameDetails->getShortName(),
182
                'route_name' => $routeName,
183
            ],
184
            'show' => [
185
                'helper' => $helper,
186
                'base_layout_exists' => $baseLayoutExists,
187
                'entity_class_name' => $entityClassNameDetails->getShortName(),
188
                'entity_var_singular' => $entityVarSingular,
189
                'entity_identifier' => $metadata->identifier[0],
190
                'entity_fields' => $metadata->fieldMappings,
191
                'route_name' => $routeName,
192
            ],
193
        ];
194
195
        foreach ($templates as $template => $variables) {
196
            $generator->generateFile(
197
                'templates/'.$templatesPath.'/'.$template.'.html.twig',
198
                $path.'templates/'.$template.'.tpl.php',
199
                $variables
200
            );
201
        }
202
203
        $generator->writeChanges();
204
205
        $this->writeSuccessMessage($io);
206
207
        $io->text('Next: Check your new CRUD!');
208
    }
209
210
    private function getFormFieldsFromEntity(ClassMetadataInfo $metadata): array
211
    {
212
        $fields = (array) $metadata->fieldNames;
213
        // Remove the primary key field if it's not managed manually
214
        if (!$metadata->isIdentifierNatural()) {
215
            $fields = array_diff($fields, $metadata->identifier);
216
        }
217
        foreach ($metadata->associationMappings as $fieldName => $relation) {
218
            if (ClassMetadataInfo::ONE_TO_MANY !== $relation['type']) {
219
                $fields[] = $fieldName;
220
            }
221
        }
222
223
        return $fields;
224
    }
225
}
226