Completed
Pull Request — master (#4191)
by Craig
05:27
created

StartCommand::doAdmin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 8
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula Foundation - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\Bundle\CoreInstallerBundle\Command\Install;
15
16
use Symfony\Component\Console\Input\InputInterface;
17
use Symfony\Component\Console\Input\InputOption;
18
use Symfony\Component\Console\Output\OutputInterface;
19
use Symfony\Component\Console\Style\SymfonyStyle;
20
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
21
use Symfony\Contracts\Translation\TranslatorInterface;
22
use Zikula\Bundle\CoreBundle\Helper\LocalDotEnvHelper;
23
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
24
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
25
use Zikula\Bundle\CoreInstallerBundle\Command\AbstractCoreInstallerCommand;
26
use Zikula\Bundle\CoreInstallerBundle\Form\Type\CreateAdminType;
27
use Zikula\Bundle\CoreInstallerBundle\Form\Type\DbCredsType;
28
use Zikula\Bundle\CoreInstallerBundle\Form\Type\LocaleType;
29
use Zikula\Bundle\CoreInstallerBundle\Form\Type\RequestContextType;
30
use Zikula\Bundle\CoreInstallerBundle\Helper\ControllerHelper;
31
use Zikula\Bundle\CoreInstallerBundle\Helper\DbCredsHelper;
32
use Zikula\Bundle\CoreInstallerBundle\Helper\ParameterHelper;
33
use Zikula\MailerModule\Form\Type\MailTransportConfigType;
34
use Zikula\MailerModule\Helper\MailTransportHelper;
35
use Zikula\SettingsModule\Api\ApiInterface\LocaleApiInterface;
36
37
class StartCommand extends AbstractCoreInstallerCommand
38
{
39
    protected static $defaultName = 'zikula:install:start';
40
41
    /**
42
     * @var bool
43
     */
44
    private $installed;
45
46
    /**
47
     * @var ControllerHelper
48
     */
49
    private $controllerHelper;
50
51
    /**
52
     * @var LocaleApiInterface
53
     */
54
    private $localeApi;
55
56
    /**
57
     * @var ParameterHelper
58
     */
59
    private $parameterHelper;
60
61
    public function __construct(
62
        ZikulaHttpKernelInterface $kernel,
63
        string $installed,
64
        ControllerHelper $controllerHelper,
65
        LocaleApiInterface $localeApi,
66
        ParameterHelper $parameterHelper,
67
        TranslatorInterface $translator
68
    ) {
69
        $this->kernel = $kernel;
70
        $this->installed = '0.0.0' !== $installed;
71
        $this->controllerHelper = $controllerHelper;
72
        $this->localeApi = $localeApi;
73
        $this->parameterHelper = $parameterHelper;
74
        parent::__construct($kernel, $translator);
75
    }
76
77
    protected function configure()
78
    {
79
        $this->setDescription('call this command first');
80
81
        foreach ($this->settings as $name => $setting) {
82
            $this->addOption(
83
                $name,
84
                null,
85
                InputOption::VALUE_REQUIRED,
86
                $setting['description'],
87
                $setting['default']
88
            );
89
        }
90
    }
91
92
    protected function execute(InputInterface $input, OutputInterface $output): int
93
    {
94
        $io = new SymfonyStyle($input, $output);
95
        $io->title($this->translator->trans('Zikula Installer Script'));
96
97
        if (true === $this->installed) {
98
            $io->error($this->translator->trans('Zikula already appears to be installed.'));
99
100
            return 1;
101
        }
102
103
        $warnings = $this->controllerHelper->initPhp();
104
        if (!empty($warnings)) {
105
            $this->printWarnings($output, $warnings);
106
107
            return 2;
108
        }
109
        $checks = $this->controllerHelper->requirementsMet();
110
        if (true !== $checks) {
0 ignored issues
show
introduced by
The condition true !== $checks is always true.
Loading history...
111
            $this->printRequirementsWarnings($output, $checks);
112
113
            return 2;
114
        }
115
116
        if ($input->isInteractive()) {
117
            $io->comment($this->translator->trans('Configuring Zikula installation in %env% environment.', ['%env%' => $this->kernel->getEnvironment()]));
118
            $io->comment($this->translator->trans('Please follow the instructions to install Zikula %version%.', ['%version%' => ZikulaKernel::VERSION]));
119
        }
120
121
        // get the settings from user input
122
        $settings = $this->doLocale($input, $output);
123
        $settings = array_merge($settings, $this->doRequestContext($input, $output));
124
        if (!$this->doDBCreds($input, $output)) {
125
            $io->error(sprintf('Cannot write database DSN to %s file.', '/.env.local'));
126
        }
127
        if (!$this->doMailer($input, $output)) {
128
            $io->error(sprintf('Cannot write mailer DSN to %s file.', '/.env.local'));
129
        }
130
        $settings = array_merge($settings, $this->doAdmin($input, $output));
131
132
        if ($input->isInteractive()) {
133
            $io->success($this->translator->trans('Configuration successful. Please verify your parameters below:'));
134
            $io->comment($this->translator->trans('(Admin credentials have been encoded to make them json-safe.)'));
135
        }
136
137
        $this->printSettings($settings, $io);
138
        $io->newLine();
139
140
        if ($input->isInteractive()) {
141
            $confirmation = $io->confirm($this->translator->trans('Start installation?'), true);
142
143
            if (!$confirmation) {
144
                $io->error($this->translator->trans('Installation aborted'));
145
146
                return 3;
147
            }
148
        }
149
150
        // write parameters into config/services_custom.yaml and env vars into .env.local
151
        $this->parameterHelper->initializeParameters($settings);
152
153
        $io->success($this->translator->trans('First stage of installation complete. Run `php bin/console zikula:install:finish` to complete the installation.'));
154
155
        return 0;
156
    }
157
158
    private function doLocale(InputInterface $input, OutputInterface $output): array
159
    {
160
        return $this->getHelper('form')->interactUsingForm(LocaleType::class, $input, $output, [
161
            'choices' => $this->localeApi->getSupportedLocaleNames(),
162
            'choice_loader' => null
163
        ]);
164
    }
165
166
    private function doRequestContext(InputInterface $input, OutputInterface $output): array
167
    {
168
        $data = $this->getHelper('form')->interactUsingForm(RequestContextType::class, $input, $output);
169
        foreach ($data as $k => $v) {
170
            $newKey = str_replace(':', '.', $k);
171
            $data[$newKey] = $v;
172
            unset($data[$k]);
173
        }
174
175
        return $data;
176
    }
177
178
    private function doDBCreds(InputInterface $input, OutputInterface $output): bool
179
    {
180
        $data = $this->getHelper('form')->interactUsingForm(DbCredsType::class, $input, $output);
181
        $dbCredsHelper = new DbCredsHelper();
182
        $databaseUrl = $dbCredsHelper->buildDatabaseUrl($data);
183
        try {
184
            $vars = ['DATABASE_URL' => '!\'' . $databaseUrl . '\''];
185
            $helper = new LocalDotEnvHelper($this->kernel->getProjectDir());
186
            $helper->writeLocalEnvVars($vars);
187
188
            return true;
189
        } catch (IOExceptionInterface $exception) {
190
            return false;
191
        }
192
    }
193
194
    private function doMailer(InputInterface $input, OutputInterface $output): bool
195
    {
196
        $data = $this->getHelper('form')->interactUsingForm(MailTransportConfigType::class, $input, $output);
197
198
        return (new MailTransportHelper($this->kernel->getProjectDir()))->handleFormData($data);
199
    }
200
201
    private function doAdmin(InputInterface $input, OutputInterface $output): array
202
    {
203
        $data = $this->getHelper('form')->interactUsingForm(CreateAdminType::class, $input, $output);
204
        foreach ($data as $k => $v) {
205
            $data[$k] = base64_encode($v); // encode so values are 'safe' for json
206
        }
207
208
        return $data;
209
    }
210
}
211