Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

Command/GenerateAdminListCommand.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\GeneratorBundle\Command;
4
5
use Kunstmaan\GeneratorBundle\Generator\AdminListGenerator;
6
use Kunstmaan\GeneratorBundle\Helper\EntityValidator;
7
use Kunstmaan\GeneratorBundle\Helper\GeneratorUtils;
8
use Kunstmaan\GeneratorBundle\Helper\Sf4AppBundle;
9
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCommand;
10
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
use Symfony\Component\Console\Question\ConfirmationQuestion;
15
use Symfony\Component\Console\Question\Question;
16
use Symfony\Component\HttpKernel\Bundle\Bundle;
17
use Symfony\Component\HttpKernel\Kernel;
18
19
/**
20
 * Generates a KunstmaanAdminList
21
 */
22
class GenerateAdminListCommand extends GenerateDoctrineCommand
23
{
24
    /**
25
     * @see Command
26
     */
27
    protected function configure()
28
    {
29
        $this
30
            ->setDefinition(
31
                array(
32
                    new InputOption(
33
                        'entity',
34
                        '',
35
                        InputOption::VALUE_REQUIRED,
36
                        'The entity class name to create an admin list for (shortcut notation)'
37
                    ),
38
                    new InputOption(
39
                        'sortfield',
40
                        '',
41
                        InputOption::VALUE_OPTIONAL,
42
                        'The name of the sort field if entity needs to be sortable'
43
                    ),
44
                )
45
            )
46
            ->setDescription('Generates a KunstmaanAdminList')
47
            ->setHelp(
48
                <<<'EOT'
49
                The <info>kuma:generate:adminlist</info> command generates an AdminList for a Doctrine ORM entity.
50
51
<info>php bin/console kuma:generate:adminlist Bundle:Entity</info>
52
EOT
53
            )
54
            ->setName('kuma:generate:adminlist');
55
    }
56
57
    /**
58
     * Executes the command.
59
     *
60
     * @param InputInterface  $input  An InputInterface instance
61
     * @param OutputInterface $output An OutputInterface instance
62
     *
63
     * @throws \RuntimeException
64
     *
65
     * @return int|null|void
66
     */
67
    protected function execute(InputInterface $input, OutputInterface $output)
68
    {
69
        $questionHelper = $this->getQuestionHelper();
70
71
        GeneratorUtils::ensureOptionsProvided($input, array('entity'));
72
73
        $entity = EntityValidator::validate($input->getOption('entity'));
74
        if (Kernel::VERSION_ID < 40000) {
75
            list($bundle, $entity) = $this->parseShortcutNotation($entity);
76
77
            $entityClass = $this->getContainer()->get('doctrine')->getAliasNamespace($bundle) . '\\' . $entity;
78
            $metadata = $this->getEntityMetadata($entityClass)[0];
79
            $bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
80
        } else {
81
            $entityClass = $entity;
82
            $em = $this->getContainer()->get('doctrine')->getManager();
83
84
            $metadata = $em->getClassMetadata($entityClass);
85
            $bundle = new Sf4AppBundle($this->getContainer()->getParameter('kernel.project_dir'));
86
        }
87
88
        $questionHelper->writeSection($output, 'AdminList Generation');
89
90
        $generator = $this->getGenerator($this->getApplication()->getKernel()->getBundle('KunstmaanGeneratorBundle'));
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Console\Application as the method getKernel() does only exist in the following sub-classes of Symfony\Component\Console\Application: Symfony\Bundle\FrameworkBundle\Console\Application. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
91
        $generator->setQuestion($questionHelper);
92
        $generator->generate($bundle, $entityClass, $metadata, $output, $input->getOption('sortfield'));
93
94
        if (Kernel::VERSION_ID >= 40000) {
95
            return;
96
        }
97
98
        $parts = explode('\\', $entity);
99
        $entityClass = array_pop($parts);
100
101
        $this->updateRouting($questionHelper, $input, $output, $bundle, $entityClass);
102
    }
103
104
    /**
105
     * Interacts with the user.
106
     *
107
     * @param InputInterface  $input  An InputInterface instance
108
     * @param OutputInterface $output An OutputInterface instance
109
     */
110
    protected function interact(InputInterface $input, OutputInterface $output)
111
    {
112
        $questionHelper = $this->getQuestionHelper();
113
        $questionHelper->writeSection($output, 'Welcome to the Kunstmaan admin list generator');
114
115
        // entity
116
        $entity = null;
117
118
        try {
119
            $entity = $input->getOption('entity') ? EntityValidator::validate($input->getOption('entity')) : null;
120
        } catch (\Exception $error) {
121
            $output->writeln(
122
                $questionHelper->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error')
123
            );
124
        }
125
126
        if (is_null($entity)) {
127
            $output->writeln(
128
                array(
129
                    '',
130
                    'This command helps you to generate an admin list for your entity.',
131
                    '',
132
                    'You must use the shortcut notation like <comment>AcmeBlogBundle:Post</comment>.',
133
                    '',
134
                )
135
            );
136
137
            $question = new Question($questionHelper->getQuestion('The entity shortcut name', $entity), $entity);
138
            $question->setValidator(['\Kunstmaan\GeneratorBundle\Helper\EntityValidator', 'validate']);
139
            $entity = $questionHelper->ask($input, $output, $question);
140
            $input->setOption('entity', $entity);
141
142
            $question = new Question($questionHelper->getQuestion('The name of the sort field if entity needs to be sortable', false, '?'), false);
143
            $sortfield = $questionHelper->ask($input, $output, $question);
144
            $input->setOption('sortfield', $sortfield);
145
        }
146
    }
147
148
    /**
149
     * @param QuestionHelper  $questionHelper The question helper
150
     * @param InputInterface  $input          The command input
151
     * @param OutputInterface $output         The command output
152
     * @param Bundle          $bundle         The bundle
153
     * @param string          $entityClass    The classname of the entity
154
     */
155
    protected function updateRouting(
156
        QuestionHelper $questionHelper,
157
        InputInterface $input,
158
        OutputInterface $output,
159
        Bundle $bundle,
160
        $entityClass
161
    ) {
162
        $adminKey = $this->getContainer()->getParameter('kunstmaan_admin.admin_prefix');
163
        $auto = true;
164
        $multilang = false;
165
        if ($input->isInteractive()) {
166
            $confirmationQuestion = new ConfirmationQuestion(
167
                $questionHelper->getQuestion('Is it a multilanguage site', 'yes', '?'), true
168
            );
169
            $multilang = $questionHelper->ask($input, $output, $confirmationQuestion);
170
            $confirmationQuestion = new ConfirmationQuestion(
171
                $questionHelper->getQuestion('Do you want to update the routing automatically', 'yes', '?'), true
172
            );
173
            $auto = $questionHelper->ask($input, $output, $confirmationQuestion);
174
        }
175
176
        $prefix = $multilang ? '/{_locale}' : '';
177
178
        $code = sprintf("%s:\n", strtolower($bundle->getName()) . '_' . strtolower($entityClass) . '_admin_list');
179
        $code .= sprintf("    resource: '@%s/Controller/%sAdminListController.php'\n", $bundle->getName(), $entityClass, "'");
180
        $code .= "    type:     annotation\n";
181
        $code .= sprintf("    prefix:   %s/%s/%s/\n", $prefix, $adminKey, strtolower($entityClass));
182
        if ($multilang) {
183
            $code .= "    requirements:\n";
184
            $code .= "         _locale: \"%requiredlocales%\"\n";
185
        }
186
187
        if ($auto) {
188
            $file = $bundle->getPath() . '/Resources/config/routing.yml';
189
            $content = '';
190
191
            if (file_exists($file)) {
192
                $content = file_get_contents($file);
193
            } elseif (!is_dir($dir = dirname($file))) {
194
                mkdir($dir, 0777, true);
195
            }
196
197
            $content .= "\n";
198
            $content .= $code;
199
200
            if (false === file_put_contents($file, $content)) {
201
                $output->writeln(
202
                    $questionHelper->getHelperSet()->get('formatter')->formatBlock(
203
                        'Failed adding the content automatically',
204
                        'error'
205
                    )
206
                );
207
            } else {
208
                return;
209
            }
210
        }
211
212
        $output->writeln('Add the following to your routing.yml');
213
        $output->writeln('/*******************************/');
214
        $output->write($code);
215
        $output->writeln('/*******************************/');
216
    }
217
218
    /**
219
     * KunstmaanTestBundle_TestEntity:
220
     * resource: "@KunstmaanTestBundle/Controller/TestEntityAdminListController.php"
221
     * type:     annotation
222
     * prefix:   /{_locale}/%kunstmaan_admin.admin_prefix%/testentity/
223
     * requirements:
224
     * _locale: "%requiredlocales%"
225
     */
226
    protected function createGenerator()
227
    {
228
        return new AdminListGenerator(GeneratorUtils::getFullSkeletonPath('adminlist'));
229
    }
230
}
231