Completed
Pull Request — 2.x (#210)
by Christian
09:33
created

GenerateCommand::generate()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 56

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 56
rs 8.6488
c 0
b 0
f 0
cc 5
nc 5
nop 3

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
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\EasyExtendsBundle\Command;
15
16
use Sonata\EasyExtendsBundle\Bundle\BundleMetadata;
17
use Sonata\EasyExtendsBundle\Generator\BundleGenerator;
18
use Sonata\EasyExtendsBundle\Generator\OdmGenerator;
19
use Sonata\EasyExtendsBundle\Generator\OrmGenerator;
20
use Sonata\EasyExtendsBundle\Generator\PHPCRGenerator;
21
use Sonata\EasyExtendsBundle\Generator\SerializerGenerator;
22
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
23
use Symfony\Component\Console\Input\InputArgument;
24
use Symfony\Component\Console\Input\InputInterface;
25
use Symfony\Component\Console\Input\InputOption;
26
use Symfony\Component\Console\Output\OutputInterface;
27
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
28
use Symfony\Component\HttpKernel\KernelInterface;
29
30
/**
31
 * Generate Application entities from bundle entities.
32
 *
33
 * NEXT_MAJOR: stop extending ContainerAwareCommand.
34
 *
35
 * @author Thomas Rabaix <[email protected]>
36
 */
37
class GenerateCommand extends ContainerAwareCommand
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Bundle\Framework...d\ContainerAwareCommand has been deprecated with message: since Symfony 4.2, use {@see Command} instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
38
{
39
    /**
40
     * @var KernelInterface|null
41
     */
42
    private $kernel;
43
44
    /**
45
     * @var BundleGenerator|null
46
     */
47
    private $bundleGenerator;
48
49
    /**
50
     * @var OrmGenerator|null
51
     */
52
    private $ormGenerator;
53
54
    /**
55
     * @var OdmGenerator|null
56
     */
57
    private $odmGenerator;
58
59
    /**
60
     * @var PHPCRGenerator|null
61
     */
62
    private $phpcrGenerator;
63
64
    /**
65
     * @var SerializerGenerator|null
66
     */
67
    private $serializerGenerator;
68
69
    public function __construct(
70
        string $name = null,
71
        KernelInterface $kernel = null,
72
        BundleGenerator $bundleGenerator = null,
73
        OrmGenerator $ormGenerator = null,
74
        OdmGenerator $odmGenerator = null,
75
        PHPCRGenerator $phpcrGenerator = null,
76
        SerializerGenerator $serializerGenerator = null
77
    ) {
78
        parent::__construct($name);
79
80
        if (null === $kernel) {
81
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
82
                'Not providing a kernel to "%s" is deprecated since 2.x and will no longer be possible in 3.0',
83
                \get_class($this)
84
            ), E_USER_DEPRECATED);
85
        }
86
87
        if (null === $bundleGenerator) {
88
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
89
                'Not providing a bundleGenerator to "%s" is deprecated since 2.x and will no longer be possible in 3.0',
90
                \get_class($this)
91
            ), E_USER_DEPRECATED);
92
        }
93
94
        if (null === $ormGenerator) {
95
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
96
                'Not providing a ormGenerator to "%s" is deprecated since 2.x and will no longer be possible in 3.0',
97
                \get_class($this)
98
            ), E_USER_DEPRECATED);
99
        }
100
101
        if (null === $odmGenerator) {
102
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
103
                'Not providing a odmGenerator to "%s" is deprecated since 2.x and will no longer be possible in 3.0',
104
                \get_class($this)
105
            ), E_USER_DEPRECATED);
106
        }
107
108
        if (null === $phpcrGenerator) {
109
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
110
                'Not providing a phpcrGenerator to "%s" is deprecated since 2.x and will no longer be possible in 3.0',
111
                \get_class($this)
112
            ), E_USER_DEPRECATED);
113
        }
114
115
        if (null === $serializerGenerator) {
116
            @trigger_error(sprintf(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
117
                'Not providing a serializerGenerator to "%s" is deprecated since 2.x and will no longer be possible in 3.0',
118
                \get_class($this)
119
            ), E_USER_DEPRECATED);
120
        }
121
122
        $this->kernel = $kernel;
123
        $this->bundleGenerator = $bundleGenerator;
124
        $this->ormGenerator = $ormGenerator;
125
        $this->odmGenerator = $odmGenerator;
126
        $this->phpcrGenerator = $phpcrGenerator;
127
        $this->serializerGenerator = $serializerGenerator;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    protected function configure()
134
    {
135
        $this
136
            ->setName('sonata:easy-extends:generate')
137
            ->setHelp(<<<'EOT'
138
The <info>easy-extends:generate:entities</info> command generating a valid bundle structure from a Vendor Bundle.
139
140
  <info>ie: ./app/console sonata:easy-extends:generate SonataUserBundle</info>
141
EOT
142
            );
143
144
        $this->setDescription('Create entities used by Sonata\'s bundles');
145
146
        $this->addArgument('bundle', InputArgument::IS_ARRAY, 'The bundle name to "easy-extends"');
147
        $this->addOption('dest', 'd', InputOption::VALUE_OPTIONAL, 'The base folder where the Application will be created', false);
148
        $this->addOption('namespace', 'ns', InputOption::VALUE_OPTIONAL, 'The namespace for the classes', false);
149
        $this->addOption('namespace_prefix', 'nsp', InputOption::VALUE_OPTIONAL, 'The namespace prefix for the classes', false);
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    protected function execute(InputInterface $input, OutputInterface $output): ?int
156
    {
157
        $destOption = $input->getOption('dest');
158
        if ($destOption) {
159
            $dest = realpath($destOption);
160
            if (false === $dest) {
161
                throw new \RuntimeException(sprintf('The provided destination folder \'%s\' does not exist!', $destOption));
162
            }
163
        } else {
164
            $dest = $this->getKernel()->getRootDir();
0 ignored issues
show
Deprecated Code introduced by
The method Symfony\Component\HttpKe...Interface::getRootDir() has been deprecated with message: since Symfony 4.2

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
165
        }
166
167
        $namespace = $input->getOption('namespace');
168
        if ($namespace) {
169
            if (!preg_match('/^(?:(?:[[:alnum:]]+|:vendor)\\\\?)+$/', $namespace)) {
170
                throw new \InvalidArgumentException('The provided namespace \'%s\' is not a valid namespace!', $namespace);
171
            }
172
        } else {
173
            $namespace = 'Application\:vendor';
174
        }
175
176
        $configuration = [
177
            'application_dir' => sprintf('%s%s%s', $dest, \DIRECTORY_SEPARATOR, str_replace('\\', \DIRECTORY_SEPARATOR, $namespace)),
178
            'namespace' => $namespace,
179
            'namespace_prefix' => '',
180
        ];
181
182
        if ($namespacePrefix = $input->getOption('namespace_prefix')) {
183
            $configuration['namespace_prefix'] = rtrim($namespacePrefix, '\\').'\\';
184
        }
185
186
        $bundleNames = $input->getArgument('bundle');
187
188
        if (empty($bundleNames)) {
189
            $output->writeln('');
190
            $output->writeln('<error>You must provide a bundle name!</error>');
191
            $output->writeln('');
192
            $output->writeln('  Bundles availables :');
193
            /** @var BundleInterface $bundle */
194
            foreach ($this->getKernel()->getBundles() as $bundle) {
195
                $bundleMetadata = new BundleMetadata($bundle, $configuration);
196
197
                if (!$bundleMetadata->isExtendable()) {
198
                    continue;
199
                }
200
201
                $output->writeln(sprintf('     - %s', $bundle->getName()));
202
            }
203
204
            $output->writeln('');
205
        } else {
206
            foreach ($bundleNames as $bundleName) {
0 ignored issues
show
Bug introduced by
The expression $bundleNames of type string|array<integer,string> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
207
                $processed = $this->generate($bundleName, $configuration, $output);
208
209
                if (!$processed) {
210
                    throw new \RuntimeException(sprintf(
211
                        '<error>The bundle \'%s\' does not exist or is not registered in the kernel!</error>',
212
                        $bundleName
213
                    ));
214
                }
215
            }
216
        }
217
218
        $output->writeln('done!');
219
220
        return 0;
221
    }
222
223
    /**
224
     * Generates a bundle entities from a bundle name.
225
     *
226
     * @param string          $bundleName
227
     * @param array           $configuration
228
     * @param OutputInterface $output
229
     *
230
     * @return bool
231
     */
232
    protected function generate($bundleName, array $configuration, $output)
233
    {
234
        $processed = false;
235
236
        /** @var BundleInterface $bundle */
237
        foreach ($this->getKernel()->getBundles() as $bundle) {
238
            if ($bundle->getName() !== $bundleName) {
239
                continue;
240
            }
241
242
            $processed = true;
243
            $bundleMetadata = new BundleMetadata($bundle, $configuration);
244
245
            // generate the bundle file.
246
            if (!$bundleMetadata->isExtendable()) {
247
                $output->writeln(sprintf('Ignoring bundle : "<comment>%s</comment>"', $bundleMetadata->getClass()));
248
249
                continue;
250
            }
251
252
            // generate the bundle file
253
            if (!$bundleMetadata->isValid()) {
254
                $output->writeln(sprintf(
255
                    '%s : <comment>wrong directory structure</comment>',
256
                    $bundleMetadata->getClass()
257
                ));
258
259
                continue;
260
            }
261
262
            $output->writeln(sprintf('Processing bundle : "<info>%s</info>"', $bundleMetadata->getName()));
263
264
            $this->getBundleGenerator()
265
                ->generate($output, $bundleMetadata);
266
267
            $output->writeln(sprintf('Processing Doctrine ORM : "<info>%s</info>"', $bundleMetadata->getName()));
268
            $this->getOrmGenerator()
269
                ->generate($output, $bundleMetadata);
270
271
            $output->writeln(sprintf('Processing Doctrine ODM : "<info>%s</info>"', $bundleMetadata->getName()));
272
            $this->getOdmGenerator()
273
                ->generate($output, $bundleMetadata);
274
275
            $output->writeln(sprintf('Processing Doctrine PHPCR : "<info>%s</info>"', $bundleMetadata->getName()));
276
            $this->getPHPCRGenerator()
277
                ->generate($output, $bundleMetadata);
278
279
            $output->writeln(sprintf('Processing Serializer config : "<info>%s</info>"', $bundleMetadata->getName()));
280
            $this->getSerializerGenerator()
281
                ->generate($output, $bundleMetadata);
282
283
            $output->writeln('');
284
        }
285
286
        return $processed;
287
    }
288
289
    private function getKernel(): KernelInterface
290
    {
291
        if (null === $this->kernel) {
292
            return $this->getContainer()->get('kernel');
293
        }
294
295
        return $this->kernel;
296
    }
297
298
    private function getBundleGenerator(): BundleGenerator
299
    {
300
        if (null === $this->bundleGenerator) {
301
            return $this->getContainer()->get('sonata.easy_extends.generator.bundle');
302
        }
303
304
        return $this->bundleGenerator;
305
    }
306
307
    private function getOrmGenerator(): OrmGenerator
308
    {
309
        if (null === $this->ormGenerator) {
310
            return $this->getContainer()->get('sonata.easy_extends.generator.orm');
311
        }
312
313
        return $this->ormGenerator;
314
    }
315
316
    private function getOdmGenerator(): OdmGenerator
317
    {
318
        if (null === $this->odmGenerator) {
319
            return $this->getContainer()->get('sonata.easy_extends.generator.odm');
320
        }
321
322
        return $this->odmGenerator;
323
    }
324
325
    private function getPHPCRGenerator(): PHPCRGenerator
326
    {
327
        if (null === $this->phpcrGenerator) {
328
            return $this->getContainer()->get('sonata.easy_extends.generator.phpcr');
329
        }
330
331
        return $this->phpcrGenerator;
332
    }
333
334
    private function getSerializerGenerator(): SerializerGenerator
335
    {
336
        if (null === $this->serializerGenerator) {
337
            return $this->getContainer()->get('sonata.easy_extends.generator.serializer');
338
        }
339
340
        return $this->serializerGenerator;
341
    }
342
}
343