Completed
Pull Request — master (#4265)
by Craig
05:16
created

UpgradeCommand::configure()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 0
dl 0
loc 15
rs 9.9332
c 0
b 0
f 0
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;
15
16
use Symfony\Component\Console\Helper\ProgressBar;
17
use Symfony\Component\Console\Input\InputInterface;
18
use Symfony\Component\Console\Input\InputOption;
19
use Symfony\Component\Console\Output\OutputInterface;
20
use Symfony\Component\Console\Style\SymfonyStyle;
21
use Symfony\Contracts\Translation\TranslatorInterface;
22
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaHttpKernelInterface;
23
use Zikula\Bundle\CoreBundle\HttpKernel\ZikulaKernel;
24
use Zikula\Bundle\CoreBundle\YamlDumper;
25
use Zikula\Bundle\CoreInstallerBundle\Controller\UpgraderController;
26
use Zikula\Bundle\CoreInstallerBundle\Form\Type\LocaleType;
27
use Zikula\Bundle\CoreInstallerBundle\Form\Type\LoginType;
28
use Zikula\Bundle\CoreInstallerBundle\Form\Type\RequestContextType;
29
use Zikula\Bundle\CoreInstallerBundle\Helper\ControllerHelper;
30
use Zikula\Bundle\CoreInstallerBundle\Helper\MigrationHelper;
31
use Zikula\Bundle\CoreInstallerBundle\Helper\StageHelper;
32
use Zikula\Bundle\CoreInstallerBundle\Stage\Upgrade\AjaxUpgraderStage;
33
use Zikula\SettingsModule\Api\ApiInterface\LocaleApiInterface;
34
35
class UpgradeCommand extends AbstractCoreInstallerCommand
36
{
37
    protected static $defaultName = 'zikula:upgrade';
38
39
    /**
40
     * @var string
41
     */
42
    private $installed;
43
44
    /**
45
     * @var ControllerHelper
46
     */
47
    private $controllerHelper;
48
49
    /**
50
     * @var MigrationHelper
51
     */
52
    private $migrationHelper;
53
54
    /**
55
     * @var LocaleApiInterface
56
     */
57
    private $localeApi;
58
59
    /**
60
     * @var StageHelper
61
     */
62
    private $stageHelper;
63
64
    /**
65
     * @var AjaxUpgraderStage
66
     */
67
    private $ajaxUpgraderStage;
68
69
    /**
70
     * @var array
71
     */
72
    private $selectedSettings = [
73
        'username',
74
        'password',
75
        'locale',
76
        'router:request_context:host',
77
        'router:request_context:scheme',
78
        'router:request_context:base_url'
79
    ];
80
81
    public function __construct(
82
        ZikulaHttpKernelInterface $kernel,
83
        ControllerHelper $controllerHelper,
84
        MigrationHelper $migrationHelper,
85
        LocaleApiInterface $localeApi,
86
        StageHelper $stageHelper,
87
        AjaxUpgraderStage $ajaxUpgraderStage,
88
        TranslatorInterface $translator,
89
        string $installed
90
    ) {
91
        $this->controllerHelper = $controllerHelper;
92
        $this->migrationHelper = $migrationHelper;
93
        $this->localeApi = $localeApi;
94
        $this->stageHelper = $stageHelper;
95
        $this->ajaxUpgraderStage = $ajaxUpgraderStage;
96
        $this->installed = $installed;
97
        parent::__construct($kernel, $translator);
98
    }
99
100
    protected function configure()
101
    {
102
        $this->setDescription('Upgrade Zikula from the command line.');
103
104
        foreach ($this->settings as $name => $setting) {
105
            if (!in_array($name, $this->selectedSettings, true)) {
106
                // only use selected settings for upgrade
107
                continue;
108
            }
109
            $this->addOption(
110
                $name,
111
                null,
112
                InputOption::VALUE_REQUIRED,
113
                $setting['description'],
114
                $setting['default']
115
            );
116
        }
117
    }
118
119
    protected function execute(InputInterface $input, OutputInterface $output): int
120
    {
121
        if (version_compare($this->installed, UpgraderController::ZIKULACORE_MINIMUM_UPGRADE_VERSION, '<')) {
122
            $output->writeln($this->translator->trans('The currently installed version of Zikula (%currentVersion%) is too old. You must upgrade to version %minimumVersion% before you can use this upgrade.', ['%currentVersion%' => $this->installed, '%minimumVersion%' => UpgraderController::ZIKULACORE_MINIMUM_UPGRADE_VERSION]));
123
124
            return 1;
125
        }
126
127
        $io = new SymfonyStyle($input, $output);
128
        $io->title($this->translator->trans('Zikula Upgrader Script'));
129
        $io->section($this->translator->trans('*** UPGRADING TO ZIKULA CORE %version% ***', ['%version%' => ZikulaKernel::VERSION]));
130
        $io->text($this->translator->trans('Upgrading Zikula in %env% environment.', ['%env%' => $this->kernel->getEnvironment()]));
131
132
        $warnings = $this->controllerHelper->initPhp();
133
        if (!empty($warnings)) {
134
            $this->printWarnings($output, $warnings);
135
136
            return 2;
137
        }
138
139
        $yamlManager = new YamlDumper($this->kernel->getProjectDir() . '/config', 'services_custom.yaml');
140
        // tell the core that we are upgrading
141
        $yamlManager->setParameter('upgrading', true);
142
143
        $this->migrateUsers($io, $output);
144
145
        // get the settings from user input
146
        $settings = $this->getHelper('form')->interactUsingForm(LocaleType::class, $input, $output, [
147
            'choices' => $this->localeApi->getSupportedLocaleNames(),
148
            'choice_loader' => null
149
        ]);
150
151
        $data = $this->getHelper('form')->interactUsingForm(LoginType::class, $input, $output);
152
        foreach ($data as $k => $v) {
153
            $data[$k] = base64_encode($v); // encode so values are 'safe' for json
154
        }
155
        $settings = array_merge($settings, $data);
156
157
        $data = $this->getHelper('form')->interactUsingForm(RequestContextType::class, $input, $output);
158
        foreach ($data as $k => $v) {
159
            $newKey = str_replace(':', '.', $k);
160
            $data[$newKey] = $v;
161
            unset($data[$k]);
162
        }
163
        $settings = array_merge($settings, $data);
164
165
        $this->printSettings($settings, $io);
166
        $io->newLine();
167
168
        // write the parameters into config/services_custom.yaml
169
        $params = array_merge($yamlManager->getParameters(), $settings);
170
        $yamlManager->setParameters($params);
171
172
        // upgrade!
173
        $this->stageHelper->handleAjaxStage($this->ajaxUpgraderStage, $io);
174
175
        $io->success($this->translator->trans('UPGRADE COMPLETE!'));
176
177
        return 0;
178
    }
179
180
    private function migrateUsers(SymfonyStyle $io, OutputInterface $output): void
181
    {
182
        if (version_compare($this->installed, '2.0.0', '>=')) {
183
            return;
184
        }
185
        $count = $this->migrationHelper->countUnMigratedUsers();
186
        if ($count > 0) {
187
            $io->text($this->translator->trans('Beginning user migration...'));
188
            $userMigrationMaxuid = (int)$this->migrationHelper->getMaxUnMigratedUid();
189
            $progressBar = new ProgressBar($output, (int)ceil($count / MigrationHelper::BATCH_LIMIT));
190
            $progressBar->start();
191
            $lastUid = 0;
192
            do {
193
                $result = $this->migrationHelper->migrateUsers($lastUid);
194
                $lastUid = $result['lastUid'];
195
                $progressBar->advance();
196
            } while ($lastUid < $userMigrationMaxuid);
197
            $progressBar->finish();
198
            $io->success($this->translator->trans('User migration complete!'));
199
        } else {
200
            $io->text($this->translator->trans('There was no need to migrate any users.'));
201
        }
202
    }
203
}
204