Completed
Push — master ( 91fdab...75a7b9 )
by
unknown
13: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\EntityManager;
6
use Doctrine\ORM\EntityManagerInterface;
7
use FOS\UserBundle\Model\GroupManagerInterface;
8
use Kunstmaan\AdminBundle\Entity\Group;
9
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
10
use Symfony\Component\Console\Input\ArrayInput;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
use Symfony\Component\Console\Question\ChoiceQuestion;
16
use Symfony\Component\Console\Question\Question;
17
use Symfony\Component\Console\Exception\InvalidArgumentException;
18
19
/**
20
 * Symfony CLI command to create a user using bin/console kuma:user:create <username_of_the_user>
21
 *
22
 * @final since 5.1
23
 * NEXT_MAJOR extend from `Command` and remove `$this->getContainer` usages
24
 */
25
class CreateUserCommand extends ContainerAwareCommand
26
{
27
    /** @var EntityManagerInterface */
28
    private $em;
29
30
    /** @var GroupManagerInterface */
31
    private $groupManager;
32
33
    /** @var string */
34
    private $userClassname;
35
36
    /** @var string */
37
    private $defaultLocale;
38
39
    /** @var array */
40
    protected $groups = [];
41
42
    public function __construct(/* EntityManagerInterface */ $em = null, GroupManagerInterface $groupManager = null, $userClassname = null, $defaultLocale = null)
43
    {
44
        parent::__construct();
45
46
        if (!$em instanceof EntityManagerInterface) {
47
            @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);
48
49
            $this->setName(null === $em ? 'kuma:user:create' : $em);
50
51
            return;
52
        }
53
54
        $this->em = $em;
55
        $this->groupManager = $groupManager;
56
        $this->userClassname = $userClassname;
57
        $this->defaultLocale = $defaultLocale;
58
    }
59
60
    protected function configure()
61
    {
62
        parent::configure();
63
64
        $this->setName('kuma:user:create')
65
            ->setDescription('Create a user.')
66
            ->setDefinition(array(
67
                new InputArgument('username', InputArgument::REQUIRED, 'The username'),
68
                new InputArgument('email', InputArgument::REQUIRED, 'The email'),
69
                new InputArgument('password', InputArgument::REQUIRED, 'The password'),
70
                new InputArgument('locale', InputArgument::OPTIONAL, 'The locale (language)'),
71
                new InputOption('group', null, InputOption::VALUE_REQUIRED, 'The group(s) the user should belong to'),
72
                new InputOption('super-admin', null, InputOption::VALUE_NONE, 'Set the user as super admin'),
73
                new InputOption('inactive', null, InputOption::VALUE_NONE, 'Set the user as inactive'),
74
            ))
75
            ->setHelp(<<<EOT
76
The <info>kuma:user:create</info> command creates a user:
77
78
  <info>php bin/console kuma:user:create matthieu --group=Users</info>
79
80
This interactive shell will ask you for an email and then a password.
81
82
You can alternatively specify the email, password and locale and group as extra arguments:
83
84
  <info>php bin/console kuma:user:create matthieu [email protected] mypassword en --group=Users</info>
85
86
You can create a super admin via the super-admin flag:
87
88
  <info>php bin/console kuma:user:create admin --super-admin --group=Administrators</info>
89
90
You can create an inactive user (will not be able to log in):
91
92
  <info>php bin/console kuma:user:create thibault --inactive --group=Users</info>
93
94
<comment>Note:</comment> You have to specify at least one group.
95
96
EOT
97
            );
98
    }
99
100
    protected function initialize(InputInterface $input, OutputInterface $output)
101
    {
102
        $this->groups = $this->getGroups();
103
    }
104
105
106
    /**
107
     * Executes the current command.
108
     *
109
     * @param InputInterface $input The input
110
     * @param OutputInterface $output The output
111
     *
112
     * @return int
113
     */
114
    protected function execute(InputInterface $input, OutputInterface $output)
115
    {
116
        if (null === $this->em) {
117
            $this->em = $this->getContainer()->get('doctrine.orm.entity_manager');
118
            $this->groupManager = $this->getContainer()->get('fos_user.group_manager');
119
            $this->userClassname = $this->getContainer()->getParameter('fos_user.model.user.class');
120
            $this->defaultLocale = $this->getContainer()->getParameter('kunstmaan_admin.default_admin_locale');
121
        }
122
123
        $username = $input->getArgument('username');
124
        $email = $input->getArgument('email');
125
        $password = $input->getArgument('password');
126
        $locale = $input->getArgument('locale');
127
        $superAdmin = $input->getOption('super-admin');
128
        $inactive = $input->getOption('inactive');
129
        $groupOption = $input->getOption('group');
130
131
        if (null === $locale) {
132
            $locale = $this->defaultLocale;
133
        }
134
        $command = $this->getApplication()->find('fos:user:create');
135
        $arguments = array(
136
            'command' => 'fos:user:create',
137
            'username' => $username,
138
            'email' => $email,
139
            'password' => $password,
140
            '--super-admin' => $superAdmin,
141
            '--inactive' => $inactive,
142
        );
143
144
        $input = new ArrayInput($arguments);
145
        $command->run($input, $output);
146
147
        // Fetch user that was just created
148
        $user = $this->em->getRepository($this->userClassname)->findOneBy(array('username' => $username));
149
150
        // Attach groups
151
        $groupOutput = [];
152
153
154
        foreach (explode(',', $groupOption) as $groupId) {
155
156
            if ((int)$groupId === 0) {
157
                foreach ($this->groups as $value) {
158
                    if ($groupId === $value->getName()) {
159
                        $group = $value;
160
                        break;
161
                    }
162
                }
163
            } else {
164
                $group = $this->groups[$groupId];
165
            }
166
167
            if (isset($group) && $group instanceof Group) {
168
                $groupOutput[] = $group->getName();
169
                $user->getGroups()->add($group);
170
            } else {
171
                throw new \RuntimeException(
172
                    'The selected group(s) can\'t be found.'
173
                );
174
            }
175
        }
176
177
        // Set admin interface locale and enable password changed
178
        $user->setAdminLocale($locale);
179
        $user->setPasswordChanged(true);
180
181
        // Persist
182
        $this->em->persist($user);
183
        $this->em->flush();
184
185
        $output->writeln(sprintf('Added user <comment>%s</comment> to groups <comment>%s</comment>', $input->getArgument('username'), implode(',', $groupOutput)));
186
    }
187
188
    /**
189
     * Interacts with the user.
190
     *
191
     * @param InputInterface $input The input
192
     * @param OutputInterface $output The output
193
     *
194
     * @throws \InvalidArgumentException
195
     *
196
     * @return void
197
     */
198
    protected function interact(InputInterface $input, OutputInterface $output)
199
    {
200 View Code Duplication
        if (!$input->getArgument('username')) {
201
            $question = New Question('Please choose a username:');
202
            $question->setValidator(function ($username) {
203
                if (null === $username) {
204
                    throw new \InvalidArgumentException('Username can not be empty');
205
                }
206
207
                return $username;
208
            });
209
            $username = $this->getHelper('question')->ask(
210
                $input,
211
                $output,
212
                $question
213
            );
214
            $input->setArgument('username', $username);
215
        }
216
217 View Code Duplication
        if (!$input->getArgument('email')) {
218
            $question = New Question('Please choose an email:');
219
            $question->setValidator(function ($email) {
220
                if (null === $email) {
221
                    throw new \InvalidArgumentException('Email can not be empty');
222
                }
223
224
                return $email;
225
            });
226
            $email = $this->getHelper('question')->ask(
227
                $input,
228
                $output,
229
                $question
230
            );
231
            $input->setArgument('email', $email);
232
        }
233
234
        if (!$input->getArgument('password')) {
235
236
            $question = New Question('Please choose a password:');
237
            $question->setHidden(true);
238
            $question->setHiddenFallback(false);
239
            $question->setValidator(function ($password) {
240
                if (null === $password) {
241
                    throw new \InvalidArgumentException('Password can not be empty');
242
                }
243
244
                return $password;
245
            });
246
            $password = $this->getHelper('question')->ask(
247
                $input,
248
                $output,
249
                $question
250
            );
251
252
            $input->setArgument('password', $password);
253
        }
254
255
        if (!$input->getArgument('locale')) {
256
            $locale = $this->getHelper('question')->ask(
257
                $input,
258
                $output,
259
                new Question('Please enter the locale (or leave empty for default admin locale):')
260
            );
261
            $input->setArgument('locale', $locale);
262
        }
263
264
        if (!$input->getOption('group')) {
265
            $question = new ChoiceQuestion(
266
                'Please enter the group(s) the user should be a member of (multiple possible, separated by comma):',
267
                $this->groups,
268
                ''
269
            );
270
            $question->setMultiselect(true);
271
            $question->setValidator(function ($groupsInput) {
272
273
                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...
274
                    throw new \RuntimeException('No user group(s) could be found');
275
                }
276
277
                // Validate that the chosen group options exist in the available groups
278
                $groupNames = array_unique(explode(',', $groupsInput));
279
                if (count(array_intersect_key(array_flip($groupNames),$this->groups)) !== count($groupNames)) {
280
                    throw new InvalidArgumentException('You have chosen non existing group(s)');
281
                }
282
283
                if ($groupsInput === '') {
284
                    throw new \RuntimeException(
285
                        'Group(s) must be of type integer and can not be empty'
286
                    );
287
                }
288
                return $groupsInput;
289
            });
290
291
            // Group has to be imploded because $input->setOption expects a string
292
            $groups = $this->getHelper('question')->ask($input, $output, $question);
293
294
            $input->setOption('group', $groups);
295
        }
296
    }
297
298
    private function getGroups()
299
    {
300
        $groups = $this->groupManager->findGroups();
301
302
        // reindexing the array, using the db id as the key
303
        $newGroups = [];
304
        foreach($groups as $group) {
305
            $newGroups[$group->getId()] = $group;
306
        }
307
308
        return $newGroups;
309
    }
310
}
311