Completed
Push — master ( 550482...257fa6 )
by Loïc
15s
created

SetupCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 1
nc 1
nop 4
1
<?php
2
3
/*
4
 * This file is part of AppName.
5
 *
6
 * (c) Monofony
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace App\Command\Installer;
13
14
use App\Entity\AdminUser;
15
use Doctrine\Common\Persistence\ObjectManager;
16
use Sylius\Component\Resource\Factory\FactoryInterface;
17
use Sylius\Component\Resource\Repository\RepositoryInterface;
18
use Symfony\Component\Console\Command\Command;
19
use Symfony\Component\Console\Helper\QuestionHelper;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Output\OutputInterface;
22
use Symfony\Component\Console\Question\Question;
23
use Symfony\Component\Validator\Constraints\Email;
24
use Symfony\Component\Validator\Constraints\NotBlank;
25
use Symfony\Component\Validator\ConstraintViolationListInterface;
26
use Symfony\Component\Validator\Validator\ValidatorInterface;
27
use Webmozart\Assert\Assert;
28
29
final class SetupCommand extends Command
30
{
31
    /**
32
     * @var ObjectManager
33
     */
34
    private $adminUserManager;
35
36
    /**
37
     * @var FactoryInterface
38
     */
39
    private $adminUserFactory;
40
41
    /**
42
     * @var RepositoryInterface
43
     */
44
    private $adminUserRepository;
45
46
    /**
47
     * @var ValidatorInterface
48
     */
49
    private $validator;
50
51
    /**
52
     * @param ObjectManager       $adminUserManager
53
     * @param FactoryInterface    $adminUserFactory
54
     * @param RepositoryInterface $adminUserRepository
55
     * @param ValidatorInterface  $validator
56
     */
57
    public function __construct(
58
        ObjectManager $adminUserManager,
59
        FactoryInterface $adminUserFactory,
60
        RepositoryInterface $adminUserRepository,
61
        ValidatorInterface $validator
62
    ) {
63
        $this->adminUserManager = $adminUserManager;
64
        $this->adminUserFactory = $adminUserFactory;
65
        $this->adminUserRepository = $adminUserRepository;
66
        $this->validator = $validator;
67
68
        parent::__construct();
69
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74
    protected function configure()
75
    {
76
        $this
77
            ->setName('app:install:setup')
78
            ->setDescription('Sylius configuration setup.')
79
            ->setHelp(<<<EOT
80
The <info>%command.name%</info> command allows user to configure basic Sylius data.
81
EOT
82
            )
83
        ;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89
    protected function execute(InputInterface $input, OutputInterface $output)
90
    {
91
        $this->setupAdministratorUser($input, $output);
92
    }
93
94
    /**
95
     * @param InputInterface  $input
96
     * @param OutputInterface $output
97
     *
98
     * @return int
99
     */
100
    protected function setupAdministratorUser(InputInterface $input, OutputInterface $output)
101
    {
102
        $output->writeln('Create your administrator account.');
103
104
        try {
105
            $user = $this->configureNewUser($this->adminUserFactory->createNew(), $input, $output);
106
        } catch (\InvalidArgumentException $exception) {
107
            return 0;
108
        }
109
110
        $user->setEnabled(true);
111
112
        $this->adminUserManager->persist($user);
113
        $this->adminUserManager->flush();
114
115
        $output->writeln('Administrator account successfully registered.');
116
    }
117
118
    /**
119
     * @param AdminUser       $user
120
     * @param InputInterface  $input
121
     * @param OutputInterface $output
122
     *
123
     * @return AdminUser
124
     */
125
    private function configureNewUser(AdminUser $user, InputInterface $input, OutputInterface $output)
126
    {
127
        if ($input->getOption('no-interaction')) {
128
            Assert::null($this->adminUserRepository->findOneByEmail('[email protected]'));
0 ignored issues
show
Bug introduced by
The method findOneByEmail() does not exist on Sylius\Component\Resourc...ory\RepositoryInterface. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
129
130
            $user->setEmail('[email protected]');
131
            $user->setUsername('admin');
132
            $user->setPlainPassword('admin');
133
134
            return $user;
135
        }
136
137
        $questionHelper = $this->getHelper('question');
138
139
        do {
140
            $question = $this->createEmailQuestion();
141
            $email = $questionHelper->ask($input, $output, $question);
142
            $exists = null !== $this->adminUserRepository->findOneByEmail($email);
0 ignored issues
show
Bug introduced by
The method findOneByEmail() does not exist on Sylius\Component\Resourc...ory\RepositoryInterface. Did you maybe mean findOneBy()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
143
144
            if ($exists) {
145
                $output->writeln('<error>E-Mail is already in use!</error>');
146
            }
147
        } while ($exists);
148
149
        $user->setEmail($email);
150
        $user->setUsername($email);
151
        $user->setPlainPassword($this->getAdministratorPassword($input, $output));
152
153
        return $user;
154
    }
155
156
    /**
157
     * @return Question
158
     */
159
    private function createEmailQuestion()
160
    {
161
        return (new Question('E-mail:'))
162
            ->setValidator(function ($value) {
163
                /** @var ConstraintViolationListInterface $errors */
164
                $errors = $this->validator->validate((string) $value, [new Email(), new NotBlank()]);
165
                foreach ($errors as $error) {
166
                    throw new \DomainException($error->getMessage());
167
                }
168
169
                return $value;
170
            })
171
            ->setMaxAttempts(3)
172
            ;
173
    }
174
175
    /**
176
     * @param InputInterface  $input
177
     * @param OutputInterface $output
178
     *
179
     * @return mixed
180
     */
181
    private function getAdministratorPassword(InputInterface $input, OutputInterface $output)
182
    {
183
        /** @var QuestionHelper $questionHelper */
184
        $questionHelper = $this->getHelper('question');
185
        $validator = $this->getPasswordQuestionValidator();
186
187
        do {
188
            $passwordQuestion = $this->createPasswordQuestion('Choose password:', $validator);
189
            $confirmPasswordQuestion = $this->createPasswordQuestion('Confirm password:', $validator);
190
191
            $password = $questionHelper->ask($input, $output, $passwordQuestion);
192
            $repeatedPassword = $questionHelper->ask($input, $output, $confirmPasswordQuestion);
193
194
            if ($repeatedPassword !== $password) {
195
                $output->writeln('<error>Passwords do not match!</error>');
196
            }
197
        } while ($repeatedPassword !== $password);
198
199
        return $password;
200
    }
201
202
    /**
203
     * @return \Closure
204
     */
205
    private function getPasswordQuestionValidator()
206
    {
207
        return function ($value) {
208
            /** @var ConstraintViolationListInterface $errors */
209
            $errors = $this->validator->validate($value, [new NotBlank()]);
210
            foreach ($errors as $error) {
211
                throw new \DomainException($error->getMessage());
212
            }
213
214
            return $value;
215
        };
216
    }
217
218
    /**
219
     * @param string   $message
220
     * @param \Closure $validator
221
     *
222
     * @return Question
223
     */
224
    private function createPasswordQuestion($message, \Closure $validator)
225
    {
226
        return (new Question($message))
227
            ->setValidator($validator)
228
            ->setMaxAttempts(3)
229
            ->setHidden(true)
230
            ->setHiddenFallback(false)
231
            ;
232
    }
233
}
234