Completed
Push — master ( ae5e03...0447ee )
by Jeroen
10:35 queued 04:37
created

AdminBundle/Command/CreateUserCommand.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\AdminBundle\Command;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use FOS\UserBundle\Model\GroupManagerInterface;
7
use Kunstmaan\AdminBundle\Entity\Group;
8
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
9
use Symfony\Component\Console\Input\ArrayInput;
10
use Symfony\Component\Console\Input\InputArgument;
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\ChoiceQuestion;
15
use Symfony\Component\Console\Question\Question;
16
use Symfony\Component\Console\Exception\InvalidArgumentException;
17
18
/**
19
 * Symfony CLI command to create a user using bin/console kuma:user:create <username_of_the_user>
20
 *
21
 * @final since 5.1
22
 * NEXT_MAJOR extend from `Command` and remove `$this->getContainer` usages
23
 */
24
class CreateUserCommand extends ContainerAwareCommand
25
{
26
    /** @var EntityManagerInterface */
27
    private $em;
28
29
    /** @var GroupManagerInterface */
30
    private $groupManager;
31
32
    /** @var string */
33
    private $userClassname;
34
35
    /** @var string */
36
    private $defaultLocale;
37
38
    /** @var array */
39
    protected $groups = [];
40
41
    public function __construct(/* EntityManagerInterface */ $em = null, GroupManagerInterface $groupManager = null, $userClassname = null, $defaultLocale = null)
42
    {
43
        parent::__construct();
44
45
        if (!$em instanceof EntityManagerInterface) {
46
            @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version symfony 3.4 and will be removed in symfony 4.0. If the command was registered by convention, make it a service instead. ', __METHOD__), E_USER_DEPRECATED);
47
48
            $this->setName(null === $em ? 'kuma:user:create' : $em);
49
50
            return;
51
        }
52
53
        $this->em = $em;
54
        $this->groupManager = $groupManager;
55
        $this->userClassname = $userClassname;
56
        $this->defaultLocale = $defaultLocale;
57
    }
58
59
    protected function configure()
60
    {
61
        parent::configure();
62
63
        $this->setName('kuma:user:create')
64
            ->setDescription('Create a user.')
65
            ->setDefinition(array(
66
                new InputArgument('username', InputArgument::REQUIRED, 'The username'),
67
                new InputArgument('email', InputArgument::REQUIRED, 'The email'),
68
                new InputArgument('password', InputArgument::REQUIRED, 'The password'),
69
                new InputArgument('locale', InputArgument::OPTIONAL, 'The locale (language)'),
70
                new InputOption('group', null, InputOption::VALUE_REQUIRED, 'The group(s) the user should belong to'),
71
                new InputOption('super-admin', null, InputOption::VALUE_NONE, 'Set the user as super admin'),
72
                new InputOption('inactive', null, InputOption::VALUE_NONE, 'Set the user as inactive'),
73
            ))
74
            ->setHelp(<<<'EOT'
75
The <info>kuma:user:create</info> command creates a user:
76
77
  <info>php bin/console kuma:user:create matthieu --group=Users</info>
78
79
This interactive shell will ask you for an email and then a password.
80
81
You can alternatively specify the email, password and locale and group as extra arguments:
82
83
  <info>php bin/console kuma:user:create matthieu [email protected] mypassword en --group=Users</info>
84
85
You can create a super admin via the super-admin flag:
86
87
  <info>php bin/console kuma:user:create admin --super-admin --group=Administrators</info>
88
89
You can create an inactive user (will not be able to log in):
90
91
  <info>php bin/console kuma:user:create thibault --inactive --group=Users</info>
92
93
<comment>Note:</comment> You have to specify at least one group.
94
95
EOT
96
            );
97
    }
98
99
    protected function initialize(InputInterface $input, OutputInterface $output)
100
    {
101
        $this->groups = $this->getGroups();
102
    }
103
104
    /**
105
     * Executes the current command.
106
     *
107
     * @param InputInterface  $input  The input
108
     * @param OutputInterface $output The output
109
     *
110
     * @return int
111
     */
112
    protected function execute(InputInterface $input, OutputInterface $output)
113
    {
114
        if (null === $this->em) {
115
            $this->em = $this->getContainer()->get('doctrine.orm.entity_manager');
116
            $this->groupManager = $this->getContainer()->get('fos_user.group_manager');
117
            $this->userClassname = $this->getContainer()->getParameter('fos_user.model.user.class');
118
            $this->defaultLocale = $this->getContainer()->getParameter('kunstmaan_admin.default_admin_locale');
119
        }
120
121
        $username = $input->getArgument('username');
122
        $email = $input->getArgument('email');
123
        $password = $input->getArgument('password');
124
        $locale = $input->getArgument('locale');
125
        $superAdmin = $input->getOption('super-admin');
126
        $inactive = $input->getOption('inactive');
127
        $groupOption = $input->getOption('group');
128
129
        if (null === $locale) {
130
            $locale = $this->defaultLocale;
131
        }
132
        $command = $this->getApplication()->find('fos:user:create');
133
        $arguments = array(
134
            'command' => 'fos:user:create',
135
            'username' => $username,
136
            'email' => $email,
137
            'password' => $password,
138
            '--super-admin' => $superAdmin,
139
            '--inactive' => $inactive,
140
        );
141
142
        $input = new ArrayInput($arguments);
143
        $command->run($input, $output);
144
145
        // Fetch user that was just created
146
        $user = $this->em->getRepository($this->userClassname)->findOneBy(array('username' => $username));
147
148
        // Attach groups
149
        $groupOutput = [];
150
151
        foreach (explode(',', $groupOption) as $groupId) {
152
            if ((int) $groupId === 0) {
153
                foreach ($this->groups as $value) {
154
                    if ($groupId === $value->getName()) {
155
                        $group = $value;
156
157
                        break;
158
                    }
159
                }
160
            } else {
161
                $group = $this->groups[$groupId];
162
            }
163
164
            if (isset($group) && $group instanceof Group) {
165
                $groupOutput[] = $group->getName();
166
                $user->getGroups()->add($group);
167
            } else {
168
                throw new \RuntimeException('The selected group(s) can\'t be found.');
169
            }
170
        }
171
172
        // Set admin interface locale and enable password changed
173
        $user->setAdminLocale($locale);
174
        $user->setPasswordChanged(true);
175
176
        // Persist
177
        $this->em->persist($user);
178
        $this->em->flush();
179
180
        $output->writeln(sprintf('Added user <comment>%s</comment> to groups <comment>%s</comment>', $input->getArgument('username'), implode(',', $groupOutput)));
181
182
        return 0;
183
    }
184
185
    /**
186
     * Interacts with the user.
187
     *
188
     * @param InputInterface  $input  The input
189
     * @param OutputInterface $output The output
190
     *
191
     * @throws \InvalidArgumentException
192
     */
193
    protected function interact(InputInterface $input, OutputInterface $output)
194
    {
195 View Code Duplication
        if (!$input->getArgument('username')) {
196
            $question = new Question('Please choose a username:');
197
            $question->setValidator(function ($username) {
198
                if (null === $username) {
199
                    throw new \InvalidArgumentException('Username can not be empty');
200
                }
201
202
                return $username;
203
            });
204
            $username = $this->getHelper('question')->ask(
205
                $input,
206
                $output,
207
                $question
208
            );
209
            $input->setArgument('username', $username);
210
        }
211
212 View Code Duplication
        if (!$input->getArgument('email')) {
213
            $question = new Question('Please choose an email:');
214
            $question->setValidator(function ($email) {
215
                if (null === $email) {
216
                    throw new \InvalidArgumentException('Email can not be empty');
217
                }
218
219
                return $email;
220
            });
221
            $email = $this->getHelper('question')->ask(
222
                $input,
223
                $output,
224
                $question
225
            );
226
            $input->setArgument('email', $email);
227
        }
228
229
        if (!$input->getArgument('password')) {
230
            $question = new Question('Please choose a password:');
231
            $question->setHidden(true);
232
            $question->setHiddenFallback(false);
233
            $question->setValidator(function ($password) {
234
                if (null === $password) {
235
                    throw new \InvalidArgumentException('Password can not be empty');
236
                }
237
238
                return $password;
239
            });
240
            $password = $this->getHelper('question')->ask(
241
                $input,
242
                $output,
243
                $question
244
            );
245
246
            $input->setArgument('password', $password);
247
        }
248
249
        if (!$input->getArgument('locale')) {
250
            $locale = $this->getHelper('question')->ask(
251
                $input,
252
                $output,
253
                new Question('Please enter the locale (or leave empty for default admin locale):')
254
            );
255
            $input->setArgument('locale', $locale);
256
        }
257
258
        if (!$input->getOption('group')) {
259
            $question = new ChoiceQuestion(
260
                'Please enter the group(s) the user should be a member of (multiple possible, separated by comma):',
261
                $this->groups,
262
                ''
263
            );
264
            $question->setMultiselect(true);
265
            $question->setValidator(function ($groupsInput) {
266
                if (!$this->groups) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->groups of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
267
                    throw new \RuntimeException('No user group(s) could be found');
268
                }
269
270
                // Validate that the chosen group options exist in the available groups
271
                $groupNames = array_unique(explode(',', $groupsInput));
272
                if (\count(array_intersect_key(array_flip($groupNames), $this->groups)) !== \count($groupNames)) {
273
                    throw new InvalidArgumentException('You have chosen non existing group(s)');
274
                }
275
276
                if ($groupsInput === '') {
277
                    throw new \RuntimeException('Group(s) must be of type integer and can not be empty');
278
                }
279
280
                return $groupsInput;
281
            });
282
283
            // Group has to be imploded because $input->setOption expects a string
284
            $groups = $this->getHelper('question')->ask($input, $output, $question);
285
286
            $input->setOption('group', $groups);
287
        }
288
    }
289
290
    private function getGroups()
291
    {
292
        $groups = $this->groupManager->findGroups();
293
294
        // reindexing the array, using the db id as the key
295
        $newGroups = [];
296
        foreach ($groups as $group) {
297
            $newGroups[$group->getId()] = $group;
298
        }
299
300
        return $newGroups;
301
    }
302
}
303