Test Setup Failed
Push — master ( 0c8bf0...b71d97 )
by Herberto
05:57
created

AddUserCommand::getCommandHelp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Explicit Architecture POC,
7
 * which is created on top of the Symfony Demo application.
8
 *
9
 * (c) Herberto Graça <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Acme\App\Presentation\Console\Component\User;
16
17
use Acme\App\Core\Component\User\Application\Service\UserService;
18
use Acme\App\Core\Component\User\Application\Validation\UserValidationService;
19
use Acme\App\Core\Port\Validation\PhoneNumber\PhoneNumberException;
20
use Doctrine\ORM\EntityManagerInterface;
21
use Symfony\Component\Console\Command\Command;
22
use Symfony\Component\Console\Input\InputArgument;
23
use Symfony\Component\Console\Input\InputInterface;
24
use Symfony\Component\Console\Input\InputOption;
25
use Symfony\Component\Console\Output\OutputInterface;
26
use Symfony\Component\Console\Style\SymfonyStyle;
27
use Symfony\Component\Stopwatch\Stopwatch;
28
29
/**
30
 * A console command that creates users and stores them in the database.
31
 *
32
 * To use this command, open a terminal window, enter into your project
33
 * directory and execute the following:
34
 *
35
 *     $ php bin/console app:add-user
36
 *
37
 * To output detailed information, increase the command verbosity:
38
 *
39
 *     $ php bin/console app:add-user -vv
40
 *
41
 * See https://symfony.com/doc/current/cookbook/console/console_command.html
42
 * For more advanced uses, commands can be defined as services too. See
43
 * https://symfony.com/doc/current/console/commands_as_services.html
44
 *
45
 * @author Javier Eguiluz <[email protected]>
46
 * @author Yonel Ceruto <[email protected]>
47
 */
48
class AddUserCommand extends Command
49
{
50
    /**
51
     * To make your command lazily loaded, configure the $defaultName static property,
52
     * so it will be instantiated only when the command is actually called.
53
     *
54
     * @var string
55
     */
56
    protected static $defaultName = 'app:add-user';
57
58
    /**
59
     * @var SymfonyStyle
60
     */
61
    private $io;
62
63
    /**
64
     * @var EntityManagerInterface
65
     */
66
    private $entityManager;
67
68
    /**
69
     * @var UserValidationService
70
     */
71
    private $validator;
72
73
    /**
74
     * @var UserService
75
     */
76
    private $userService;
77
78
    public function __construct(
79
        EntityManagerInterface $em,
80
        UserValidationService $validator,
81
        UserService $userService
82
    ) {
83
        parent::__construct();
84
85
        $this->entityManager = $em;
86
        $this->validator = $validator;
87
        $this->userService = $userService;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    protected function configure(): void
94
    {
95
        $this
96
            ->setDescription('Creates users and stores them in the database')
97
            ->setHelp($this->getCommandHelp())
98
            // commands can optionally define arguments and/or options (mandatory and optional)
99
            // see https://symfony.com/doc/current/components/console/console_arguments.html
100
            ->addArgument('username', InputArgument::OPTIONAL, 'The username of the new user')
101
            ->addArgument('password', InputArgument::OPTIONAL, 'The plain password of the new user')
102
            ->addArgument('email', InputArgument::OPTIONAL, 'The email of the new user')
103
            ->addArgument('mobile', InputArgument::OPTIONAL, 'The mobile number of the new user')
104
            ->addArgument('full-name', InputArgument::OPTIONAL, 'The full name of the new user')
105
            ->addOption('admin', null, InputOption::VALUE_NONE, 'If set, the user is created as an administrator');
106
    }
107
108
    /**
109
     * This optional method is the first one executed for a command after configure()
110
     * and is useful to initialize properties based on the input arguments and options.
111
     */
112
    protected function initialize(InputInterface $input, OutputInterface $output): void
113
    {
114
        // SymfonyStyle is an optional feature that Symfony provides so you can
115
        // apply a consistent look to the commands of your application.
116
        // See https://symfony.com/doc/current/console/style.html
117
        $this->io = new SymfonyStyle($input, $output);
118
    }
119
120
    /**
121
     * This method is executed after initialize() and before execute(). Its purpose
122
     * is to check if some of the options/arguments are missing and interactively
123
     * ask the user for those values.
124
     *
125
     * This method is completely optional. If you are developing an internal console
126
     * command, you probably should not implement this method because it requires
127
     * quite a lot of work. However, if the command is meant to be used by external
128
     * users, this method is a nice way to fall back and prevent errors.
129
     */
130
    protected function interact(InputInterface $input, OutputInterface $output): void
131
    {
132
        if (
133
            $input->getArgument('username') !== null
134
            && $input->getArgument('password') !== null
135
            && $input->getArgument('email') !== null
136
            && $input->getArgument('mobile') !== null
137
            && $input->getArgument('full-name') !== null
138
        ) {
139
            return;
140
        }
141
142
        $this->io->title('Add User Command Interactive Wizard');
143
        $this->io->text([
144
            'If you prefer to not use this interactive wizard, provide the',
145
            'arguments required by this command as follows:',
146
            '',
147
            ' $ php bin/console app:add-user username password [email protected]',
148
            '',
149
            'Now we\'ll ask you for the value of all the missing command arguments.',
150
        ]);
151
152
        // Ask for the username if it's not defined
153
        $username = $input->getArgument('username');
154
        if ($username !== null) {
155
            $this->io->text(' > <info>Username</info>: ' . $username);
156
        } else {
157
            $username = $this->io->ask('Username', null, [$this->validator, 'validateUsername']);
158
            $input->setArgument('username', $username);
159
        }
160
161
        // Ask for the password if it's not defined
162
        $password = $input->getArgument('password');
163
        if ($password !== null) {
164
            $this->io->text(' > <info>Password</info>: ' . str_repeat('*', mb_strlen($password)));
165
        } else {
166
            $password = $this->io->askHidden('Password (your type will be hidden)', [$this->validator, 'validatePassword']);
167
            $input->setArgument('password', $password);
168
        }
169
170
        // Ask for the email if it's not defined
171
        $email = $input->getArgument('email');
172
        if ($email !== null) {
173
            $this->io->text(' > <info>Email</info>: ' . $email);
174
        } else {
175
            $email = $this->io->ask('Email', null, [$this->validator, 'validateEmail']);
176
            $input->setArgument('email', $email);
177
        }
178
179
        // Ask for the mobile if it's not defined
180
        $mobile = $input->getArgument('mobile');
181
        if ($mobile !== null) {
182
            $this->io->text(' > <info>Mobile</info>: ' . $mobile);
183
        } else {
184
            $mobile = $this->io->ask('Mobile', null, [$this->validator, 'validateMobile']);
185
            $input->setArgument('mobile', $mobile);
186
        }
187
188
        // Ask for the full name if it's not defined
189
        $fullName = $input->getArgument('full-name');
190
        if ($fullName !== null) {
191
            $this->io->text(' > <info>Full Name</info>: ' . $fullName);
192
        } else {
193
            $fullName = $this->io->ask('Full Name', null, [$this->validator, 'validateFullName']);
194
            $input->setArgument('full-name', $fullName);
195
        }
196
    }
197
198
    /**
199
     * This method is executed after interact() and initialize(). It usually
200
     * contains the logic to execute to complete this command task.
201
     *
202
     * @throws PhoneNumberException
203
     */
204
    protected function execute(InputInterface $input, OutputInterface $output): void
205
    {
206
        $stopwatch = new Stopwatch();
207
        $stopwatch->start('add-user-command');
208
209
        $user = $this->userService->createUser(
210
            (string) $input->getArgument('username'),
211
            (string) $input->getArgument('password'),
212
            (string) $input->getArgument('email'),
213
            (string) $input->getArgument('mobile'),
214
            (string) $input->getArgument('full-name'),
215
            (bool) $input->getOption('admin')
216
        );
217
218
        $this->entityManager->flush();
219
220
        $this->io->success(sprintf(
221
            '%s was successfully created: %s (%s)',
222
            $user->isAdmin() ? 'Administrator user' : 'User',
223
            $user->getUsername(),
224
            $user->getEmail()
225
        ));
226
227
        $event = $stopwatch->stop('add-user-command');
228
        if ($output->isVerbose()) {
229
            $this->io->comment(sprintf('New user database id: %d / Elapsed time: %.2f ms / Consumed memory: %.2f MB', $user->getId(), $event->getDuration(), $event->getMemory() / (1024 ** 2)));
230
        }
231
    }
232
233
    /**
234
     * The command help is usually included in the configure() method, but when
235
     * it's too long, it's better to define a separate method to maintain the
236
     * code readability.
237
     */
238
    private function getCommandHelp(): string
239
    {
240
        return <<<'HELP'
241
            The <info>%command.name%</info> command creates new users and saves them in the database:
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected EOF
Loading history...
242
243
              <info>php %command.full_name%</info> <comment>username password email</comment>
244
245
            By default the command creates regular users. To create administrator users,
246
            add the <comment>--admin</comment> option:
247
248
              <info>php %command.full_name%</info> username password email mobile <comment>--admin</comment>
249
250
            If you omit any of the three required arguments, the command will ask you to
251
            provide the missing values:
252
253
              # command will ask you for the email
254
              <info>php %command.full_name%</info> <comment>username password</comment>
255
256
              # command will ask you for the email and password
257
              <info>php %command.full_name%</info> <comment>username</comment>
258
259
              # command will ask you for all arguments
260
              <info>php %command.full_name%</info>
261
262
            HELP;
263
    }
264
}
265