GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 68a77d...93332e )
by Petko
04:20
created

CrudGeneratorCommand::interact()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 118
Code Lines 83

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 88
CRAP Score 7.0017

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 118
ccs 88
cts 91
cp 0.967
rs 6.4589
cc 7
eloc 83
nc 8
nop 2
crap 7.0017

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
/*
4
 * This file is part of the CrudBundle
5
 *
6
 * It is based/extended from SensioGeneratorBundle
7
 *
8
 * (c) Petko Petkov <[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 Petkopara\CrudGeneratorBundle\Command;
15
16
use Doctrine\Bundle\DoctrineBundle\Mapping\DisconnectedMetadataFactory;
17
use Petkopara\CrudGeneratorBundle\Configuration\ConfigurationBuilder;
18
use Petkopara\CrudGeneratorBundle\Generator\Guesser\MetadataGuesser;
19
use Petkopara\CrudGeneratorBundle\Generator\PetkoparaCrudGenerator;
20
use Petkopara\CrudGeneratorBundle\Generator\PetkoparaFilterGenerator;
21
use Petkopara\CrudGeneratorBundle\Generator\PetkoparaFormGenerator;
22
use Sensio\Bundle\GeneratorBundle\Command\AutoComplete\EntitiesAutoCompleter;
23
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand;
24
use Sensio\Bundle\GeneratorBundle\Command\Validators;
25
use Symfony\Component\Config\Definition\Exception\Exception;
26
use Symfony\Component\Console\Input\InputArgument;
27
use Symfony\Component\Console\Input\InputInterface;
28
use Symfony\Component\Console\Input\InputOption;
29
use Symfony\Component\Console\Output\OutputInterface;
30
use Symfony\Component\Console\Question\ConfirmationQuestion;
31
use Symfony\Component\Console\Question\Question;
32
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
33
use Symfony\Component\Yaml\Exception\RuntimeException;
34
35
class CrudGeneratorCommand extends GenerateDoctrineCrudCommand
36
{
37
38
    const FILTER_TYPE_FORM = 'form';
39
    const FILTER_TYPE_INPUT = 'input';
40
    const FILTER_TYPE_NONE = 'none';
41
42
    protected $generator;
43
    protected $formGenerator;
44
    private $filterGenerator;
45
46 15
    protected function configure()
47
    {
48
49 15
        $this
50 15
                ->setName('petkopara:generate:crud')
51 15
                ->setDescription('A CRUD generator with pagination, filters, bulk delete and bootstrap markdown.')
52 15
                ->setDefinition(array(
53 15
                    new InputArgument('entity', InputArgument::OPTIONAL, 'The entity class name to initialize (shortcut notation)'),
54 15
                    new InputOption('entity', '', InputOption::VALUE_REQUIRED, 'The entity class name to initialize (shortcut notation)'),
55 15
                    new InputOption('route-prefix', 'r', InputOption::VALUE_REQUIRED, 'The route prefix'),
56 15
                    new InputOption('template', 't', InputOption::VALUE_REQUIRED, 'The base template which will be extended by the templates', 'PetkoparaCrudGeneratorBundle::base.html.twig'),
57 15
                    new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'The format used for configuration files (php, xml, yml, or annotation)', 'annotation'),
58 15
                    new InputOption('overwrite', 'o', InputOption::VALUE_NONE, 'Overwrite any existing controller or form class when generating the CRUD contents'),
59 15
                    new InputOption('bundle-views', 'b', InputOption::VALUE_NONE, 'Whether or not to store the view files in app/Resources/views/ or in bundle dir'),
60 15
                    new InputOption('without-sorting', 'wsr', InputOption::VALUE_NONE, 'Whether or not have sorting in the index'),
61 15
                    new InputOption('without-page-size', 'wps', InputOption::VALUE_NONE, 'Whether or not to show items per page select in the index'),
62 15
                    new InputOption('without-write', 'ww', InputOption::VALUE_NONE, 'Whether or not to generate create, new and delete actions'),
63 15
                    new InputOption('without-show', 'ws', InputOption::VALUE_NONE, 'Whether or not to generate create, new and delete actions'),
64 15
                    new InputOption('without-bulk', 'wb', InputOption::VALUE_NONE, 'Whether or not to generate bulk actions'),
65 15
                    new InputOption('filter-type', 'ft', InputOption::VALUE_REQUIRED, 'What type of filtrations to be used. Multi search input, Form filter or none', 'form'),
66 15
                ))
67 15
                ->setHelp(<<<EOT
68
The <info>%command.name%</info> command generates a CRUD based on a Doctrine entity.
69
70
The default command only generates the list and show actions.
71
72
<info>php %command.full_name% --entity=AcmeBlogBundle:Post --route-prefix=post_admin</info>
73
74
Using the --without-write to not generate the new, edit, bulk and delete actions.
75
                
76
Using the --bundle-views option store the view files in the bundles dir.
77
                
78
Using the --without-bulk  use this option tp not generate bulk actions code.
79
                
80
Using the --template option allows to set base template from which the crud views to overide.
81
                
82
<info>php %command.full_name% doctrine:generate:crud --entity=AcmeBlogBundle:Post --route-prefix=post_admin </info>
83
84
Every generated file is based on a template. There are default templates but they can be overridden by placing custom templates in one of the following locations, by order of priority:
85
86
<info>BUNDLE_PATH/Resources/CrudGeneratorBundle/skeleton/crud
87
APP_PATH/Resources/CrudGeneratorBundle/skeleton/crud</info>
88
89
And
90
91
<info>__bundle_path__/Resources/CrudGeneratorBundle/skeleton/form
92
__project_root__/app/Resources/CrudGeneratorBundle/skeleton/form</info>
93
94
EOT
95 15
        );
96 15
    }
97
98
    protected function createGenerator($bundle = null)
99
    {
100
        return new PetkoparaCrudGenerator($this->getContainer()->get('filesystem'), $this->getContainer()->getParameter('kernel.root_dir'));
101
    }
102
103
    protected function getSkeletonDirs(BundleInterface $bundle = null)
104
    {
105
        $skeletonDirs = array();
106
        if (isset($bundle) && is_dir($dir = $bundle->getPath() . '/Resources/PetkoparaCrudGeneratorBundle/skeleton')) {
107
            $skeletonDirs[] = $dir;
108
        }
109
110
        if (is_dir($dir = $this->getContainer()->get('kernel')->getRootdir() . '/Resources/PetkoparaCrudGeneratorBundle/skeleton')) {
111
            $skeletonDirs[] = $dir;
112
        }
113
114
        $skeletonDirs[] = $this->getContainer()->get('kernel')->locateResource('@PetkoparaCrudGeneratorBundle/Resources/skeleton');
115
        $skeletonDirs[] = $this->getContainer()->get('kernel')->locateResource('@PetkoparaCrudGeneratorBundle/Resources');
116
117
        return $skeletonDirs;
118
    }
119
120 11
    protected function interact(InputInterface $input, OutputInterface $output)
121
    {
122
123 11
        $questionHelper = $this->getQuestionHelper();
124 11
        $questionHelper->writeSection($output, 'Welcome to the Petkopara CRUD generator');
125
126
        // namespace
127 11
        $output->writeln(array(
128 11
            '',
129 11
            'This command helps you generate CRUD controllers and templates.',
130 11
            '',
131 11
            'First, give the name of the existing entity for which you want to generate a CRUD',
132 11
            '(use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>)',
133 11
            '',
134 11
        ));
135
136 11
        if ($input->hasArgument('entity') && $input->getArgument('entity') != '') {
137
            $input->setOption('entity', $input->getArgument('entity'));
138
        }
139
140 11
        $question = new Question($questionHelper->getQuestion('The Entity shortcut name', $input->getOption('entity')), $input->getOption('entity'));
141 11
        $question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateEntityName'));
142
143
144 11
        $autocompleter = new EntitiesAutoCompleter($this->getContainer()->get('doctrine')->getManager());
145 11
        $autocompleteEntities = $autocompleter->getSuggestions();
146 11
        $question->setAutocompleterValues($autocompleteEntities);
147 11
        $entity = $questionHelper->ask($input, $output, $question);
148
149 11
        $input->setOption('entity', $entity);
150 11
        list($bundle, $entity) = $this->parseShortcutNotation($entity);
151
152
        try {
153 11
            $entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle) . '\\' . $entity;
154 11
            $this->getEntityMetadata($entityClass);
155 11
        } catch (\Exception $e) {
156
            throw new \RuntimeException(sprintf('Entity "%s" does not exist in the "%s" bundle. You may have mistyped the bundle name or maybe the entity doesn\'t exist yet (create it first with the "doctrine:generate:entity" command).', $entity, $bundle));
157
        }
158
159
        // write?
160 11
        $withoutWrite = $input->getOption('without-write') ? true : false; //default false
161
162 11
        $output->writeln(array(
163 11
            '',
164 11
            'By default, the generator creates all actions: list and show, new, update, and delete.',
165 11
            'You can also ask it to generate only "list and show" actions:',
166 11
            '',
167 11
        ));
168 11
        $question = new ConfirmationQuestion($questionHelper->getQuestion('Do you want to generate the "write" actions', $withoutWrite ? 'no' : 'yes', '?', $withoutWrite), $withoutWrite);
169 11
        $withoutWrite = $questionHelper->ask($input, $output, $question);
170 11
        $input->setOption('without-write', $withoutWrite);
171
172
        // filters?
173 11
        $filterType = $input->getOption('filter-type');
174 11
        $output->writeln(array(
175 11
            '',
176 11
            'By default, the generator generate filter code.',
177 11
             '<comment>form</comment> to use LexikFormFilterBundle to search in the entity.',
178 11
             '<comment>input</comment> to use PetkoparaMultiSearchBundle to search only with one input in the entity.',
179 11
             '<comment>none</comment> use this to not generate any filter code.',
180 11
            '',
181 11
        ));
182 11
        $question = new Question($questionHelper->getQuestion('Filter Type (form, input, none)', $filterType), $filterType);
183 11
        $question->setValidator(array('Petkopara\CrudGeneratorBundle\Command\CrudValidators', 'validateFilterType'));
184 11
        $filterType = $questionHelper->ask($input, $output, $question);
185 11
        $input->setOption('filter-type', $filterType);
186
187
188
        // template?
189 11
        $template = $input->getOption('template');
190 11
        $output->writeln(array(
191 11
            '',
192 11
            'By default, the created views extends the CrudGeneratorBundle::base.html.twig',
193 11
            'You can also set your template which the views to extend, for example base.html.twig ',
194 11
            '',
195 11
        ));
196 11
        $question = new Question($questionHelper->getQuestion('Base template for the views', $template), $template);
197 11
        $template = $questionHelper->ask($input, $output, $question);
198 11
        $input->setOption('template', $template);
199
200
201
        // format
202 11
        $format = $input->getOption('format');
203 11
        $output->writeln(array(
204 11
            '',
205 11
            'Determine the format to use for the generated CRUD.',
206 11
            '',
207 11
        ));
208 11
        $question = new Question($questionHelper->getQuestion('Configuration format (yml, xml, php, or annotation)', $format), $format);
209 11
        $question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateFormat'));
210 11
        $format = $questionHelper->ask($input, $output, $question);
211 11
        $input->setOption('format', $format);
212
213
        // route prefix
214 11
        $prefix = $this->getRoutePrefix($input, $entity);
215 11
        $output->writeln(array(
216 11
            '',
217 11
            'Determine the routes prefix (all the routes will be "mounted" under this',
218 11
            'prefix: /prefix/, /prefix/new, ...).',
219 11
            '',
220 11
        ));
221 11
        $prefix = $questionHelper->ask($input, $output, new Question($questionHelper->getQuestion('Routes prefix', '/' . $prefix), '/' . $prefix));
222 11
        $input->setOption('route-prefix', $prefix);
223
224
        // summary
225 11
        $output->writeln(array(
226 11
            '',
227 11
            $this->getHelper('formatter')->formatBlock('Summary before generation', 'bg=blue;fg=white', true),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Console\Helper\HelperInterface as the method formatBlock() does only exist in the following implementations of said interface: Symfony\Component\Console\Helper\FormatterHelper, Symfony\Component\Console\Helper\FormatterHelper.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
228 11
            '',
229 11
            sprintf('You are going to generate a CRUD controller for "<info>%s:%s</info>"', $bundle, $entity),
230 11
            sprintf('Using the "<info>%s</info>" format.', $format),
231 11
            sprintf('Route prefix "<info>%s</info>" format.', $prefix),
232 11
            sprintf('Base template "<info>%s</info>".', $template),
233 11
            sprintf('With write "<info>%s</info>".', (!$withoutWrite) ? 'yes' : 'no'),
234 11
            sprintf('Filters "<info>%s</info>".', $filterType),
235 11
            '',
236 11
        ));
237 11
    }
238
239
    /**
240
     * @see Command
241
     */
242 15
    protected function execute(InputInterface $input, OutputInterface $output)
243
    {
244 15
        $questionHelper = $this->getQuestionHelper();
245
246 15
        if ($input->isInteractive()) {
247 11
            $question = new ConfirmationQuestion($questionHelper->getQuestion('Do you confirm generation', 'yes', '?'), true);
248 11
            if (!$questionHelper->ask($input, $output, $question)) {
249
                $output->writeln('<error>Command aborted</error>');
250
                return 1;
251
            }
252 11
        }
253
254 15
        $entity = Validators::validateEntityName($input->getOption('entity'));
255 15
        list($bundle, $entity) = $this->parseShortcutNotation($entity);
256
257
        //get the options
258 15
        $format = Validators::validateFormat($input->getOption('format'));
259 15
        $prefix = $this->getRoutePrefix($input, $entity);
260 15
        $withoutWrite = $input->getOption('without-write'); //default with write
261 15
        $filterType = CrudValidators::validateFilterType($input->getOption('filter-type'));
262 15
        $withoutBulk = $input->getOption('without-bulk');
263 15
        $withoutShow = $input->getOption('without-show');
264 15
        $withoutSorting = $input->getOption('without-sorting');
265 15
        $withoutPageSize = $input->getOption('without-page-size');
266 15
        $bundleViews = $input->getOption('bundle-views');
267 15
        $template = $input->getOption('template');
268
269 15
        $forceOverwrite = $input->getOption('overwrite');
270
271 15
        $questionHelper->writeSection($output, 'CRUD generation');
272
273
        try {
274 15
            $entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle) . '\\' . $entity;
275 15
            $metadata = $this->getEntityMetadata($entityClass);
276 15
        } catch (Exception $e) {
277
            throw new RuntimeException(sprintf('Entity "%s" does not exist in the "%s" bundle. Create it with the "doctrine:generate:entity" command and then execute this command again.', $entity, $bundle));
278
        }
279
280 15
        $bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
281
282
283 15
        $configBuilder = new ConfigurationBuilder();
284
        $configuration = $configBuilder
285 15
                ->setBaseTemplate($template)
286 15
                ->setBundleViews($bundleViews)
287 15
                ->setFilterType($filterType)
288 15
                ->setWithoutBulk($withoutBulk)
289 15
                ->setWithoutShow($withoutShow)
290 15
                ->setWithoutWrite($withoutWrite)
291 15
                ->setWithoutSorting($withoutSorting)
292 15
                ->setWithoutPageSize($withoutPageSize)
293 15
                ->setOverwrite($forceOverwrite)
294 15
                ->setFormat($format)
295 15
                ->setRoutePrefix($prefix)
296 15
                ->getConfiguration()
297 15
        ;
298 15
        $generator = $this->getGenerator($bundle);
299
300 15
        $generator->generateCrud($bundle, $entity, $metadata[0], $configuration);
301
302 15
        $output->writeln('Generating the CRUD code: <info>OK</info>');
303
304 15
        $errors = array();
305 15
        $runner = $questionHelper->getRunner($output, $errors);
306
307
        // form
308 15
        if ($withoutWrite === false) {
309 13
            $this->generateForm($bundle, $entity, $metadata, $forceOverwrite);
310 13
            $output->writeln('Generating the Form code: <info>OK</info>');
311 13
        }
312
313 15
        if ($filterType !== self::FILTER_TYPE_NONE) {
314
315 14
            $this->generateFilter($bundle, $entity, $metadata, $forceOverwrite, $filterType);
316 14
            $output->writeln('Generating the Filter code: <info>OK</info>');
317 14
        }
318
        // routing
319 15
        $output->write('Updating the routing: ');
320 15
        if ('annotation' != $format) {
321 4
            $runner($this->updateRouting($questionHelper, $input, $output, $bundle, $format, $entity, $prefix));
322 4
        } else {
323 11
            $runner($this->updateAnnotationRouting($bundle, $entity, $prefix));
324
        }
325
326 15
        $questionHelper->writeGeneratorSummary($output, $errors);
327 15
    }
328
329
    /**
330
     * Tries to generate filtlers if they don't exist yet and if we need write operations on entities.
331
     * @param string $entity
332
     */
333 14
    protected function generateFilter($bundle, $entity, $metadata, $forceOverwrite = false, $type = self::FILTER_TYPE_INPUT)
334
    {
335 14
        $this->getFilterGenerator($bundle)->generate($bundle, $entity, $metadata[0], $forceOverwrite, $type);
336 14
    }
337
338 14 View Code Duplication
    protected function getFilterGenerator($bundle = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
339
    {
340 14
        if (null === $this->filterGenerator) {
341
            $metadataGuesser = new MetadataGuesser(new DisconnectedMetadataFactory($this->getContainer()->get('doctrine')));
342
            $this->filterGenerator = new PetkoparaFilterGenerator($metadataGuesser);
343
            $this->filterGenerator->setSkeletonDirs($this->getSkeletonDirs($bundle));
344
        }
345
346 14
        return $this->filterGenerator;
347
    }
348
349 13 View Code Duplication
    protected function getFormGenerator($bundle = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
350
    {
351 13
        if (null === $this->formGenerator) {
352
            $metadataGuesser = new MetadataGuesser(new DisconnectedMetadataFactory($this->getContainer()->get('doctrine')));
353
            $this->formGenerator = new PetkoparaFormGenerator($metadataGuesser);
354
            $this->formGenerator->setSkeletonDirs($this->getSkeletonDirs($bundle));
355
        }
356
357 13
        return $this->formGenerator;
358
    }
359
360 15
    public function setFilterGenerator(PetkoparaFilterGenerator $filterGenerator)
361
    {
362 15
        $this->filterGenerator = $filterGenerator;
363 15
    }
364
365 15
    public function setFormCrudGenerator(PetkoparaFormGenerator $formGenerator)
366
    {
367 15
        $this->formGenerator = $formGenerator;
368 15
    }
369
370
}
371