Test Setup Failed
Push — master ( 707012...baa95e )
by Craig
05:41
created

UpgradeCommand::migrateUsers()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 21
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 18
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 21
rs 9.6666
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;
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\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
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\Common\Translator\TranslatorInterface;
34
use Zikula\SettingsModule\Api\ApiInterface\LocaleApiInterface;
35
36
class UpgradeCommand extends AbstractCoreInstallerCommand
37
{
38
    /**
39
     * @var string
40
     */
41
    private $currentInstalledVersion;
42
43
    /**
44
     * @var ParameterBagInterface
45
     */
46
    private $params;
47
48
    /**
49
     * @var ZikulaHttpKernelInterface
50
     */
51
    private $kernel;
52
53
    /**
54
     * @var ControllerHelper
55
     */
56
    private $controllerHelper;
57
58
    /**
59
     * @var MigrationHelper
60
     */
61
    private $migrationHelper;
62
63
    /**
64
     * @var LocaleApiInterface
65
     */
66
    private $localeApi;
67
68
    /**
69
     * @var StageHelper
70
     */
71
    private $stageHelper;
72
73
    /**
74
     * @var array
75
     */
76
    private $selectedSettings = [
77
        'username',
78
        'password',
79
        'locale',
80
        'router:request_context:host',
81
        'router:request_context:scheme',
82
        'router:request_context:base_url'
83
    ];
84
85
    public function __construct(
86
        ZikulaHttpKernelInterface $kernel,
87
        ControllerHelper $controllerHelper,
88
        MigrationHelper $migrationHelper,
89
        LocaleApiInterface $localeApi,
90
        StageHelper $stageHelper,
91
        TranslatorInterface $translator,
92
        ParameterBagInterface $params
93
    ) {
94
        $this->kernel = $kernel;
95
        $this->controllerHelper = $controllerHelper;
96
        $this->migrationHelper = $migrationHelper;
97
        $this->localeApi = $localeApi;
98
        $this->stageHelper = $stageHelper;
99
        $this->params = $params;
100
        $this->currentInstalledVersion = $params->has(ZikulaKernel::CORE_INSTALLED_VERSION_PARAM) ? $params->get(ZikulaKernel::CORE_INSTALLED_VERSION_PARAM) : '';
101
        parent::__construct($translator);
102
    }
103
104
    protected function configure()
105
    {
106
        $this
107
            ->setDescription('Upgrade Zikula from the command line.')
108
            ->setName('zikula:upgrade')
109
        ;
110
        foreach ($this->settings as $name => $setting) {
111
            if (!in_array($name, $this->selectedSettings, true)) {
112
                // only use selected settings for upgrade
113
                continue;
114
            }
115
            $this->addOption(
116
                $name,
117
                null,
118
                InputOption::VALUE_REQUIRED,
119
                $setting['description'],
120
                $setting['default']
121
            );
122
        }
123
    }
124
125
    protected function execute(InputInterface $input, OutputInterface $output): int
126
    {
127
        if (version_compare($this->currentInstalledVersion, UpgraderController::ZIKULACORE_MINIMUM_UPGRADE_VERSION, '<')) {
128
            $output->writeln($this->translator->__f('The current installed version of Zikula is reporting (%1$s). You must upgrade to version (%2$s) before you can use this upgrade.', ['%1$s' => $this->currentInstalledVersion, '%2$s' => UpgraderController::ZIKULACORE_MINIMUM_UPGRADE_VERSION]));
129
130
            return 1;
131
        }
132
133
        $io = new SymfonyStyle($input, $output);
134
        $io->title($this->translator->__('Zikula Upgrader Script'));
135
        $io->section($this->translator->__f('*** UPGRADING TO ZIKULA CORE %version% ***', ['%version%' => ZikulaKernel::VERSION]));
136
        $io->text($this->translator->__f('Upgrading Zikula in %env% environment.', ['%env%' => $this->kernel->getEnvironment()]));
137
138
        $warnings = $this->controllerHelper->initPhp();
139
        if (!empty($warnings)) {
140
            $this->printWarnings($output, $warnings);
141
142
            return 2;
143
        }
144
        $checks = $this->controllerHelper->requirementsMet();
145
        if (true !== $checks) {
0 ignored issues
show
introduced by
The condition true !== $checks is always true.
Loading history...
146
            $this->printRequirementsWarnings($output, $checks);
147
148
            return 2;
149
        }
150
151
        $this->migrateUsers($io, $output);
152
153
        // avoid warning in PHP 7.2 based on ini_set() usage which is caused by any access to the
154
        // session before regeneration happens (e.g. by an event listener executed before a login)
155
        // see issue #3898 for the details
156
        $reportingLevel = error_reporting();
157
        error_reporting($reportingLevel & ~E_WARNING);
158
159
        // get the settings from user input
160
        $settings = $this->getHelper('form')->interactUsingForm(LocaleType::class, $input, $output, [
161
            'choices' => $this->localeApi->getSupportedLocaleNames(),
162
            'choice_loader' => null
163
        ]);
164
165
        $data = $this->getHelper('form')->interactUsingForm(LoginType::class, $input, $output);
166
        foreach ($data as $k => $v) {
167
            $data[$k] = base64_encode($v); // encode so values are 'safe' for json
168
        }
169
        $settings = array_merge($settings, $data);
170
171
        $data = $this->getHelper('form')->interactUsingForm(RequestContextType::class, $input, $output);
172
        foreach ($data as $k => $v) {
173
            $newKey = str_replace(':', '.', $k);
174
            $data[$newKey] = $v;
175
            unset($data[$k]);
176
        }
177
        $settings = array_merge($settings, $data);
178
179
        $this->printSettings($settings, $io);
180
        $io->newLine();
181
182
        // write the parameters to custom_parameters.yml
183
        $yamlManager = new YamlDumper($this->kernel->getProjectDir() . '/app/config', 'custom_parameters.yml');
184
        $params = array_merge($yamlManager->getParameters(), $settings);
185
        unset($params['upgrading']);
186
        $yamlManager->setParameters($params);
187
188
        // upgrade!
189
        $ajaxStage = new AjaxUpgraderStage($this->translator, $this->params);
190
        $this->stageHelper->handleAjaxStage($ajaxStage, $io);
191
192
        error_reporting($reportingLevel);
193
194
        $io->success($this->translator->__('UPGRADE COMPLETE!'));
195
196
        return 0;
197
    }
198
199
    private function migrateUsers(SymfonyStyle $io, OutputInterface $output): void
200
    {
201
        if (version_compare($this->currentInstalledVersion, '2.0.0', '>=')) {
202
            return;
203
        }
204
        $count = $this->migrationHelper->countUnMigratedUsers();
205
        if ($count > 0) {
206
            $io->text($this->translator->__('Beginning user migration...'));
207
            $userMigrationMaxuid = (int)$this->migrationHelper->getMaxUnMigratedUid();
208
            $progressBar = new ProgressBar($output, (int)ceil($count / MigrationHelper::BATCH_LIMIT));
209
            $progressBar->start();
210
            $lastUid = 0;
211
            do {
212
                $result = $this->migrationHelper->migrateUsers($lastUid);
213
                $lastUid = $result['lastUid'];
214
                $progressBar->advance();
215
            } while ($lastUid < $userMigrationMaxuid);
216
            $progressBar->finish();
217
            $io->success($this->translator->__('User migration complete!'));
218
        } else {
219
            $io->text($this->translator->__('There was no need to migrate any users.'));
220
        }
221
    }
222
}
223