Completed
Pull Request — master (#4269)
by Craig
05:48
created

StartCommand::execute()   B

Complexity

Conditions 9
Paths 50

Size

Total Lines 60
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 34
c 1
b 0
f 0
nc 50
nop 2
dl 0
loc 60
rs 8.0555

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - 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\StyleInterface;
20
use Symfony\Component\Console\Style\SymfonyStyle;
21
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
22
use Symfony\Contracts\Translation\TranslatorInterface;
23
use Zikula\Bundle\CoreBundle\Helper\LocalDotEnvHelper;
24
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
25
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
26
use Zikula\Bundle\CoreInstallerBundle\Command\AbstractCoreInstallerCommand;
27
use Zikula\Bundle\CoreInstallerBundle\Form\Type\CreateAdminType;
28
use Zikula\Bundle\CoreInstallerBundle\Form\Type\DbCredsType;
29
use Zikula\Bundle\CoreInstallerBundle\Form\Type\LocaleType;
30
use Zikula\Bundle\CoreInstallerBundle\Form\Type\RequestContextType;
31
use Zikula\Bundle\CoreInstallerBundle\Helper\DbCredsHelper;
32
use Zikula\Bundle\CoreInstallerBundle\Helper\ParameterHelper;
33
use Zikula\Bundle\CoreInstallerBundle\Helper\PhpHelper;
34
use Zikula\MailerModule\Form\Type\MailTransportConfigType;
35
use Zikula\MailerModule\Helper\MailTransportHelper;
36
use Zikula\SettingsModule\Api\ApiInterface\LocaleApiInterface;
37
38
class StartCommand extends AbstractCoreInstallerCommand
39
{
40
    protected static $defaultName = 'zikula:install:start';
41
42
    /**
43
     * @var bool
44
     */
45
    private $installed;
46
47
    /**
48
     * @var PhpHelper
49
     */
50
    private $phpHelper;
51
52
    /**
53
     * @var LocaleApiInterface
54
     */
55
    private $localeApi;
56
57
    /**
58
     * @var ParameterHelper
59
     */
60
    private $parameterHelper;
61
62
    public function __construct(
63
        ZikulaHttpKernelInterface $kernel,
64
        string $installed,
65
        PhpHelper $phpHelper,
66
        LocaleApiInterface $localeApi,
67
        ParameterHelper $parameterHelper,
68
        TranslatorInterface $translator
69
    ) {
70
        $this->kernel = $kernel;
71
        $this->installed = '0.0.0' !== $installed;
72
        $this->phpHelper = $phpHelper;
73
        $this->localeApi = $localeApi;
74
        $this->parameterHelper = $parameterHelper;
75
        parent::__construct($kernel, $translator);
76
    }
77
78
    protected function configure()
79
    {
80
        $this->setDescription('call this command first');
81
82
        foreach ($this->settings as $name => $setting) {
83
            $this->addOption(
84
                $name,
85
                null,
86
                InputOption::VALUE_REQUIRED,
87
                $setting['description'],
88
                $setting['default']
89
            );
90
        }
91
    }
92
93
    protected function execute(InputInterface $input, OutputInterface $output): int
94
    {
95
        $io = new SymfonyStyle($input, $output);
96
        $io->title($this->translator->trans('Zikula Installer Script'));
97
98
        if (true === $this->installed) {
99
            $io->error($this->translator->trans('Zikula already appears to be installed.'));
100
101
            return 1;
102
        }
103
104
        $iniWarnings = $this->phpHelper->setUp();
105
        if (!empty($iniWarnings)) {
106
            $this->printWarnings($output, $iniWarnings);
107
108
            return 2;
109
        }
110
111
        if ($input->isInteractive()) {
112
            $io->comment($this->translator->trans('Configuring Zikula installation in %env% environment.', ['%env%' => $this->kernel->getEnvironment()]));
113
            $io->comment($this->translator->trans('Please follow the instructions to install Zikula %version%.', ['%version%' => ZikulaKernel::VERSION]));
114
        }
115
116
        // get the settings from user input
117
        $settings = $this->doLocale($input, $output, $io);
118
        $settings = array_merge($settings, $this->doRequestContext($input, $output, $io));
119
        if (!$this->doDBCreds($input, $output, $io)) {
120
            $io->error($this->translator->trans('Cannot write database DSN to %file% file.', ['%file%' => '/.env.local']));
121
        }
122
        if (false === $mailSettings = $this->doMailer($input, $output, $io)) {
123
            $io->error($this->translator->trans('Cannot write mailer DSN to %file% file.', ['%file%' => '/.env.local']));
124
        } else {
125
            $settings = array_merge($settings, $mailSettings);
126
        }
127
        $settings = array_merge($settings, $this->doAdmin($input, $output, $io));
128
129
        if ($input->isInteractive()) {
130
            $io->success($this->translator->trans('Configuration successful. Please verify your parameters below:'));
131
            $io->comment($this->translator->trans('(Admin credentials have been encoded to make them json-safe.)'));
132
        }
133
134
        $this->printSettings($settings, $io);
135
        $io->newLine();
136
137
        if ($input->isInteractive()) {
138
            $confirmation = $io->confirm($this->translator->trans('Start installation?'), true);
139
140
            if (!$confirmation) {
141
                $io->error($this->translator->trans('Installation aborted'));
142
143
                return 3;
144
            }
145
        }
146
147
        // write parameters into config/services_custom.yaml and env vars into .env.local
148
        $this->parameterHelper->initializeParameters($settings);
149
150
        $io->success($this->translator->trans('First stage of installation complete. Run `php bin/console zikula:install:finish` to complete the installation.'));
151
152
        return 0;
153
    }
154
155
    private function doLocale(InputInterface $input, OutputInterface $output, StyleInterface $io): array
156
    {
157
        $io->newLine();
158
        $io->section($this->translator->trans('Locale'));
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, StyleInterface $io): array
167
    {
168
        $io->newLine();
169
        $io->section($this->translator->trans('Request context'));
170
        $data = $this->getHelper('form')->interactUsingForm(RequestContextType::class, $input, $output);
171
        foreach ($data as $k => $v) {
172
            $newKey = str_replace(':', '.', $k);
173
            $data[$newKey] = $v;
174
            unset($data[$k]);
175
        }
176
177
        return $data;
178
    }
179
180
    private function doDBCreds(InputInterface $input, OutputInterface $output, StyleInterface $io): bool
181
    {
182
        $io->newLine();
183
        $io->section($this->translator->trans('Database information'));
184
        $io->note($this->translator->trans('The database port can be left empty.'));
185
        $data = $this->getHelper('form')->interactUsingForm(DbCredsType::class, $input, $output);
186
        $dbCredsHelper = new DbCredsHelper();
187
        $databaseUrl = $dbCredsHelper->buildDatabaseUrl($data);
188
        try {
189
            $vars = ['DATABASE_URL' => '!\'' . $databaseUrl . '\''];
190
            $helper = new LocalDotEnvHelper($this->kernel->getProjectDir());
191
            $helper->writeLocalEnvVars($vars);
192
193
            return true;
194
        } catch (IOExceptionInterface $exception) {
195
            return false;
196
        }
197
    }
198
199
    private function doMailer(InputInterface $input, OutputInterface $output, StyleInterface $io) // bool|array
200
    {
201
        $io->newLine();
202
        $io->section($this->translator->trans('Mailer transport'));
203
        $io->note($this->translator->trans('Empty values are allowed for all except Mailer transport.'));
204
        $data = $this->getHelper('form')->interactUsingForm(MailTransportConfigType::class, $input, $output);
205
        $mailDsnWrite = (new MailTransportHelper($this->kernel->getProjectDir()))->handleFormData($data);
206
        if ($mailDsnWrite) {
207
            return $this->encodeArrayValues($data);
208
        }
209
210
        return false;
211
    }
212
213
    private function doAdmin(InputInterface $input, OutputInterface $output, StyleInterface $io): array
214
    {
215
        $io->newLine();
216
        $io->section($this->translator->trans('Create admin account'));
217
        $data = $this->getHelper('form')->interactUsingForm(CreateAdminType::class, $input, $output);
218
219
        return $this->encodeArrayValues($data);
220
    }
221
222
    private function encodeArrayValues(array $data): array
223
    {
224
        foreach ($data as $k => $v) {
225
            $data[$k] = base64_encode($v); // encode so values are 'safe' for json
226
        }
227
228
        return $data;
229
    }
230
}
231