Completed
Pull Request — master (#137)
by Loïc
02:18
created

SetupCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 1
nc 1
nop 3
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 Webmozart\Assert\Assert;
27
28
final class SetupCommand extends Command
29
{
30
    /**
31
     * @var ObjectManager
32
     */
33
    private $adminUserManager;
34
35
    /**
36
     * @var FactoryInterface
37
     */
38
    private $adminUserFactory;
39
40
    /**
41
     * @var RepositoryInterface
42
     */
43
    private $adminUserRepository;
44
45
    /**
46
     * @param ObjectManager       $adminUserManager
47
     * @param FactoryInterface    $adminUserFactory
48
     * @param RepositoryInterface $adminUserRepository
49
     */
50
    public function __construct(
51
        ObjectManager $adminUserManager,
52
        FactoryInterface $adminUserFactory,
53
        RepositoryInterface $adminUserRepository
54
    ) {
55
        $this->adminUserManager = $adminUserManager;
56
        $this->adminUserFactory = $adminUserFactory;
57
        $this->adminUserRepository = $adminUserRepository;
58
59
        parent::__construct();
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    protected function configure()
66
    {
67
        $this
68
            ->setName('app:install:setup')
69
            ->setDescription('Sylius configuration setup.')
70
            ->setHelp(<<<EOT
71
The <info>%command.name%</info> command allows user to configure basic Sylius data.
72
EOT
73
            )
74
        ;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    protected function execute(InputInterface $input, OutputInterface $output)
81
    {
82
        $this->setupAdministratorUser($input, $output);
83
    }
84
85
    /**
86
     * @param InputInterface  $input
87
     * @param OutputInterface $output
88
     *
89
     * @return int
90
     */
91
    protected function setupAdministratorUser(InputInterface $input, OutputInterface $output)
92
    {
93
        $output->writeln('Create your administrator account.');
94
95
        try {
96
            $user = $this->configureNewUser($this->adminUserFactory->createNew(), $input, $output);
97
        } catch (\InvalidArgumentException $exception) {
98
            return 0;
99
        }
100
101
        $user->setEnabled(true);
102
103
        $this->adminUserManager->persist($user);
104
        $this->adminUserManager->flush();
105
106
        $output->writeln('Administrator account successfully registered.');
107
    }
108
109
    /**
110
     * @param AdminUser       $user
111
     * @param InputInterface  $input
112
     * @param OutputInterface $output
113
     *
114
     * @return AdminUser
115
     */
116
    private function configureNewUser(AdminUser $user, InputInterface $input, OutputInterface $output)
117
    {
118
        if ($input->getOption('no-interaction')) {
119
            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...
120
121
            $user->setEmail('[email protected]');
122
            $user->setUsername('admin');
123
            $user->setPlainPassword('admin');
124
125
            return $user;
126
        }
127
128
        $questionHelper = $this->getHelper('question');
129
130
        do {
131
            $question = $this->createEmailQuestion();
132
            $email = $questionHelper->ask($input, $output, $question);
133
            $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...
134
135
            if ($exists) {
136
                $output->writeln('<error>E-Mail is already in use!</error>');
137
            }
138
        } while ($exists);
139
140
        $user->setEmail($email);
141
        $user->setUsername($email);
142
        $user->setPlainPassword($this->getAdministratorPassword($input, $output));
143
144
        return $user;
145
    }
146
147
    /**
148
     * @return Question
149
     */
150
    private function createEmailQuestion()
151
    {
152
        return (new Question('E-mail:'))
153
            ->setValidator(function ($value) {
154
                /** @var ConstraintViolationListInterface $errors */
155
                $errors = $this->get('validator')->validate((string) $value, [new Email(), new NotBlank()]);
0 ignored issues
show
Bug introduced by
The method get() does not seem to exist on object<App\Command\Installer\SetupCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
156
                foreach ($errors as $error) {
157
                    throw new \DomainException($error->getMessage());
158
                }
159
160
                return $value;
161
            })
162
            ->setMaxAttempts(3)
163
            ;
164
    }
165
166
    /**
167
     * @param InputInterface  $input
168
     * @param OutputInterface $output
169
     *
170
     * @return mixed
171
     */
172
    private function getAdministratorPassword(InputInterface $input, OutputInterface $output)
173
    {
174
        /** @var QuestionHelper $questionHelper */
175
        $questionHelper = $this->getHelper('question');
176
        $validator = $this->getPasswordQuestionValidator();
177
178
        do {
179
            $passwordQuestion = $this->createPasswordQuestion('Choose password:', $validator);
180
            $confirmPasswordQuestion = $this->createPasswordQuestion('Confirm password:', $validator);
181
182
            $password = $questionHelper->ask($input, $output, $passwordQuestion);
183
            $repeatedPassword = $questionHelper->ask($input, $output, $confirmPasswordQuestion);
184
185
            if ($repeatedPassword !== $password) {
186
                $output->writeln('<error>Passwords do not match!</error>');
187
            }
188
        } while ($repeatedPassword !== $password);
189
190
        return $password;
191
    }
192
193
    /**
194
     * @return \Closure
195
     */
196
    private function getPasswordQuestionValidator()
197
    {
198
        return function ($value) {
199
            /** @var ConstraintViolationListInterface $errors */
200
            $errors = $this->get('validator')->validate($value, [new NotBlank()]);
0 ignored issues
show
Bug introduced by
The method get() does not seem to exist on object<App\Command\Installer\SetupCommand>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
201
            foreach ($errors as $error) {
202
                throw new \DomainException($error->getMessage());
203
            }
204
205
            return $value;
206
        };
207
    }
208
209
    /**
210
     * @param string   $message
211
     * @param \Closure $validator
212
     *
213
     * @return Question
214
     */
215
    private function createPasswordQuestion($message, \Closure $validator)
216
    {
217
        return (new Question($message))
218
            ->setValidator($validator)
219
            ->setMaxAttempts(3)
220
            ->setHidden(true)
221
            ->setHiddenFallback(false)
222
            ;
223
    }
224
}
225