Completed
Pull Request — master (#13)
by
unknown
13:20
created

GenerateImageEntityCommand::configureCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace IrishDan\ResponsiveImageBundle\Command;
4
5
use IrishDan\ResponsiveImageBundle\Generator\ImageEntityGenerator;
6
use IrishDan\ResponsiveImageBundle\ImageEntityNameResolver;
7
use Symfony\Bundle\MakerBundle\ConsoleStyle;
8
use Symfony\Bundle\MakerBundle\DependencyBuilder;
9
use Symfony\Bundle\MakerBundle\Generator;
10
use Symfony\Bundle\MakerBundle\InputConfiguration;
11
use Symfony\Component\Console\Command\Command;
12
use Symfony\Component\Console\Command\Command as BaseCommand;
13
use Symfony\Component\Console\Input\InputInterface;
14
use Symfony\Component\Console\Input\InputOption;
15
use Symfony\Component\Console\Output\OutputInterface;
16
use Symfony\Component\Console\Question\ConfirmationQuestion;
17
use Symfony\Component\Console\Question\Question;
18
use Symfony\Component\Console\Style\SymfonyStyle;
19
20
21
/**
22
 * Class CreateImageEntityCommand
23
 *
24
 * @package IrishDan\ResponsiveImageBundle\Command
25
 */
26
class GenerateImageEntityCommand extends BaseCommand
27
{
28
    protected $entityNameResolver;
29
    protected $responsiveImageEntity;
30
    protected $bundle;
31
    protected $entityName;
32
    protected $doctrine;
33
    protected $classExists;
34
    protected $needsOverWritePermission = false;
35
    protected $overwrite = false;
36
37
    public function __construct(ImageEntityNameResolver $entityNameResolver, $doctrine)
38
    {
39
        $this->entityNameResolver = $entityNameResolver;
40
        $this->doctrine = $doctrine;
41
        $this->responsiveImageEntity = $entityNameResolver->getClassName();
42
        $this->classExists = $entityNameResolver->classExists();
43
44
        parent::__construct();
45
    }
46
47
    protected function configure()
48
    {
49
        // Limit generation to One entity for now!
50
        // We are checking two things:
51
        // If entity class name is set
52
        // If the class exists
53
54
        // @TODO: Would be good to ask for additional fields.
55
56
        $this
57
            ->setName('responsive_image:generate:entity')
58
            ->setDescription('Creates the Responsive Image entity, ' . $this->responsiveImageEntity);
59
60
        // If the Classname is not set we need to ask for it
61
        if (empty($this->responsiveImageEntity)) {
62
            $this
63
                ->setDefinition(
64
                    [
65
                        new InputOption('bundle', '', InputOption::VALUE_REQUIRED, 'The bundle for this entity'),
66
                        new InputOption('entity_name', '', InputOption::VALUE_REQUIRED, 'The name of the entity'),
67
                    ]
68
                );
69
        } // The classname is set and and the entity already exists
70
        elseif ($this->classExists) {
71
            $this->needsOverWritePermission = true;
72
73
            // Needs to have the entityName and bundle properties set
74
            // @TODO:Is there a nicer way to do this?
75
            $em = $this->doctrine->getManager();
76
            $metadata = $em->getClassMetadata($this->responsiveImageEntity);
77
            $namespace = $metadata->namespace;
78
79
            // This is bit hacky but it'll do for now.
80
            // Lets get rid of the '\Entity'.
81
            if (strpos($namespace, '\\Entity') > 0) {
82
                $namespace = substr($namespace, 0, -7);
83
            }
84
85
            $namespaceParts = explode('\\', $namespace);
86
            $this->bundle = array_pop($namespaceParts);
87
            $entityNameParts = explode('\\', $this->responsiveImageEntity);
88
            $this->entityName = array_pop($entityNameParts);
89
90
            $this
91
                ->setDefinition(
92
                    [
93
                        new InputOption(
94
                            'overwrite', '', InputOption::VALUE_NONE, 'Overwrite the existing image entity'
95
                        ),
96
                    ]
97
                );
98
        }
99
        // The classname is set but the entity does not exist.
100
        // We don't need any options for this, simple generate based on the defined classname
101
    }
102
103
    /**
104
     * @param InputInterface $input
105
     * @param OutputInterface $output
106
     */
107
    protected function interact(InputInterface $input, OutputInterface $output)
108
    {
109
        $questionHelper = $this->getQuestionHelper();
0 ignored issues
show
Bug introduced by
The method getQuestionHelper() does not seem to exist on object<IrishDan\Responsi...rateImageEntityCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
110
        $questionHelper->writeSection($output, 'Welcome to the Image entity generator');
111
112
        $message = [
113
            'This Currently only supports one Image entity',
114
            '',
115
        ];
116
117
        // If entity already exists,
118
        // get overwrite permission
119
        if ($this->needsOverWritePermission) {
120
            $message[] = sprintf('It looks like the image entity exists as %s', $this->responsiveImageEntity);
121
            $message[] = '';
122
            $message[] = sprintf(
123
                'Therefore this generator will overwrite that class, %s',
124
                $this->responsiveImageEntity
125
            );
126
127
            $output->writeln($message);
0 ignored issues
show
Documentation introduced by
$message is of type array<integer,string>, but the function expects a string|object<Symfony\Co...onsole\Output\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128
129
            // Ask whether overwrite is allowed
130
            $question = $this->createYesNoQuestion($questionHelper, $this->responsiveImageEntity);
131
            $overwrite = $questionHelper->ask($input, $output, $question);
132
133
            if ($overwrite !== 'y') {
134
                throw new \RuntimeException(
135
                    'Aborting, overwrite permission is needed.'
136
                );
137
            } else {
138
                $this->overwrite = true;
139
            }
140
        }
141
        // If class name is not set,
142
        // Ask the bundle and the entity name questions
143
        elseif (empty($this->responsiveImageEntity)) {
144
            $question = new Question(
145
                $questionHelper->getQuestion('The bundle name', $input->getOption('bundle')),
146
                $input->getOption('bundle')
147
            );
148
149
            $question->setValidator(['Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateBundleName']);
150
            $question->setNormalizer(
151
                function ($value) {
152
                    return $value ? trim($value) : '';
153
                }
154
            );
155
            $question->setMaxAttempts(2);
156
157
            $bundle = $questionHelper->ask($input, $output, $question);
158
            $input->setOption('bundle', $bundle);
159
160
            // Get the Bundle to generate it in
161
            $output->writeln(
162
                [
0 ignored issues
show
Documentation introduced by
array('', 'Now, give the...ment>Image</comment>)') is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string|object<Symfony\Co...onsole\Output\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
163
                    '',
164
                    'Now, give the name of the new entity class (eg <comment>Image</comment>)',
165
                ]
166
            );
167
168
            // Get the new class name and validate it.
169
            $question = new Question(
170
                $questionHelper->getQuestion('The entity name', $input->getOption('entity_name')),
171
                $input->getOption('entity_name')
172
            );
173
            $question->setValidator(
174
                function ($answer) {
175
                    // Should only contain letters.
176
                    $valid = preg_match('/^[a-zA-Z]+$/', $answer);
177
                    if (!$valid) {
178
                        throw new \RuntimeException(
179
                            'The class name should only contain letters'
180
                        );
181
                    }
182
183
                    return $answer;
184
                }
185
            );
186
            $question->setNormalizer(
187
                function ($value) {
188
                    return $value ? trim($value) : '';
189
                }
190
            );
191
192
            $notificationName = $questionHelper->ask($input, $output, $question);
193
            $input->setOption('entity_name', $notificationName);
194
        }
195
        // Should be all ready to generate
196
197
        // At the end we need the bundle and the entity
198
        if (empty($this->entityName) || empty($this->bundle)) {
199
            throw new \RuntimeException(
200
                'Required options have not been set'
201
            );
202
        }
203
    }
204
205
    /**
206
     * @param InputInterface $input
207
     * @param OutputInterface $output
208
     *
209
     * @return int
210
     */
211
    protected function execute(InputInterface $input, OutputInterface $output)
212
    {
213
        $questionHelper = $this->getQuestionHelper();
0 ignored issues
show
Bug introduced by
The method getQuestionHelper() does not seem to exist on object<IrishDan\Responsi...rateImageEntityCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
214
215 View Code Duplication
        if ($input->isInteractive()) {
0 ignored issues
show
Duplication introduced by
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...
216
            $question = new ConfirmationQuestion(
217
                $questionHelper->getQuestion('Do you confirm generation', 'yes', '?'),
218
                true
219
            );
220
            if (!$questionHelper->ask($input, $output, $question)) {
221
                $output->writeln('<error>Command aborted</error>');
222
223
                return 1;
224
            }
225
        }
226
227
        $style = new SymfonyStyle($input, $output);
228
229
        $bundle = $this->bundle;
230
        $name = $this->entityName;
231
232
        $style->text('Generating New doctrine entity class ' . $name . ' generated in ' . $bundle);
233
234
        try {
235
            $bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
0 ignored issues
show
Bug introduced by
The method getContainer() does not seem to exist on object<IrishDan\Responsi...rateImageEntityCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
236
        } catch (\Exception $e) {
237
            $output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
238
        }
239
240
        $generator = $this->getGenerator($bundle);
0 ignored issues
show
Bug introduced by
The method getGenerator() does not seem to exist on object<IrishDan\Responsi...rateImageEntityCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
241
        $generator->generate($bundle, $name);
242
243
        $output->writeln(sprintf('Generated the <info>%s</info> entity in <info>%s</info>', $name, $bundle->getName()));
244
        $questionHelper->writeGeneratorSummary($output, []);
245
    }
246
247
    /**
248
     * @return ImageEntityGenerator
249
     */
250
    protected function createGenerator()
251
    {
252
        return new ImageEntityGenerator(
253
            $this->getContainer()->get('filesystem'),
0 ignored issues
show
Bug introduced by
The method getContainer() does not seem to exist on object<IrishDan\Responsi...rateImageEntityCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
254
            $this->overwrite
255
        );
256
    }
257
258
    protected function createYesNoQuestion($questionHelper, $entity)
259
    {
260
        $question = new Question(
261
            $questionHelper->getQuestion(
262
                'Overwrite the existing image entity ' . $entity . '? <comment>[yes]</comment>',
263
                'overwrite'
264
            ), 'yes'
265
        );
266
        $question->setNormalizer(
267
            function ($value) {
268
                return $value[0] == 'y' ? 'y' : 'n';
269
            }
270
        );
271
        $question->setValidator(
272
            function ($answer) {
273
                // Should only contain letters.
274
                $allowed = [
275
                    'y',
276
                    'n',
277
                ];
278
                $valid = in_array($answer, $allowed);
279
                if (!$valid) {
280
                    throw new \RuntimeException(
281
                        'Only allowed values are ' . implode(', ', $allowed)
282
                    );
283
                }
284
285
                return $answer;
286
            }
287
        );
288
289
        return $question;
290
    }
291
292
    /**
293
     * Return the command name for your maker (e.g. make:report).
294
     *
295
     * @return string
296
     */
297
    public static function getCommandName(): string
298
    {
299
        // TODO: Implement getCommandName() method.
300
    }
301
302
    /**
303
     * Configure the command: set description, input arguments, options, etc.
304
     *
305
     * By default, all arguments will be asked interactively. If you want
306
     * to avoid that, use the $inputConfig->setArgumentAsNonInteractive() method.
307
     *
308
     * @param Command $command
309
     * @param InputConfiguration $inputConfig
310
     */
311
    public function configureCommand(Command $command, InputConfiguration $inputConfig)
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $inputConfig is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
312
    {
313
        // TODO: Implement configureCommand() method.
314
    }
315
316
    /**
317
     * Configure any library dependencies that your maker requires.
318
     *
319
     * @param DependencyBuilder $dependencies
320
     */
321
    public function configureDependencies(DependencyBuilder $dependencies)
0 ignored issues
show
Unused Code introduced by
The parameter $dependencies is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
322
    {
323
        // TODO: Implement configureDependencies() method.
324
    }
325
326
    /**
327
     * Called after normal code generation: allows you to do anything.
328
     *
329
     * @param InputInterface $input
330
     * @param ConsoleStyle $io
331
     * @param Generator $generator
332
     */
333
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
0 ignored issues
show
Unused Code introduced by
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $io is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $generator is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
334
    {
335
        // TODO: Implement generate() method.
336
    }
337
}
338