Completed
Push — master ( ad0611...abd676 )
by Tom
09:08 queued 04:30
created

InstallMagento::execute()   F

Complexity

Conditions 26
Paths > 20000

Size

Total Lines 195
Code Lines 138

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
c 3
b 2
f 0
dl 0
loc 195
rs 2
cc 26
eloc 138
nc 368640
nop 0

How to fix   Long Method    Complexity   

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
namespace N98\Magento\Command\Installer\SubCommand;
4
5
use N98\Magento\Command\SubCommand\AbstractSubCommand;
6
use N98\Util\OperatingSystem;
7
8
class InstallMagento extends AbstractSubCommand
9
{
10
    /**
11
     * @var int
12
     */
13
    const EXEC_STATUS_OK = 0;
14
15
    /**
16
     * @var \Closure
17
     */
18
    protected $notEmptyCallback;
19
20
    /**
21
     * @return void
22
     * @throws \Exception
23
     */
24
    public function execute()
25
    {
26
        $this->notEmptyCallback = function ($input) {
27
            if (empty($input)) {
28
                throw new \InvalidArgumentException('Please enter a value');
29
            }
30
            return $input;
31
        };
32
33
        $this->getCommand()->getApplication()->setAutoExit(false);
34
35
        $dialog = $this->getCommand()->getHelper('dialog');
36
37
        $defaults = $this->commandConfig['installation']['defaults'];
38
39
        $useDefaultConfigParams = $this->getCommand()->parseBoolOption(
40
            $this->input->getOption('useDefaultConfigParams')
41
        );
42
43
        $sessionSave = $useDefaultConfigParams ? $defaults['session-save'] : $dialog->ask(
44
            $this->output,
45
            '<question>Please enter the session save:</question> <comment>[' .
46
            $defaults['session-save'] . ']</comment>: ',
47
            $defaults['session-save']
48
        );
49
50
        $adminFrontname = $useDefaultConfigParams ? $defaults['backend-frontname'] : $dialog->askAndValidate(
51
            $this->output,
52
            '<question>Please enter the admin/backend frontname:</question> <comment>[' .
53
            $defaults['backend-frontname'] . ']</comment> ',
54
            $this->notEmptyCallback,
55
            false,
56
            $defaults['backend-frontname']
57
        );
58
59
        $currency = $useDefaultConfigParams ? $defaults['currency'] : $dialog->askAndValidate(
60
            $this->output,
61
            '<question>Please enter the default currency code:</question> <comment>[' .
62
            $defaults['currency'] . ']</comment>: ',
63
            $this->notEmptyCallback,
64
            false,
65
            $defaults['currency']
66
        );
67
68
        $locale = $useDefaultConfigParams ? $defaults['locale'] : $dialog->askAndValidate(
69
            $this->output,
70
            '<question>Please enter the locale code:</question> <comment>[' . $defaults['locale'] . ']</comment>: ',
71
            $this->notEmptyCallback,
72
            false,
73
            $defaults['locale']
74
        );
75
76
        $timezone = $useDefaultConfigParams ? $defaults['timezone'] : $dialog->askAndValidate(
77
            $this->output,
78
            '<question>Please enter the timezone:</question> <comment>[' . $defaults['timezone'] . ']</comment>: ',
79
            $this->notEmptyCallback,
80
            false,
81
            $defaults['timezone']
82
        );
83
84
        $adminUsername = $useDefaultConfigParams ? $defaults['admin-user'] : $dialog->askAndValidate(
85
            $this->output,
86
            '<question>Please enter the admin username:</question> <comment>[' .
87
            $defaults['admin-user'] . ']</comment>: ',
88
            $this->notEmptyCallback,
89
            false,
90
            $defaults['admin-user']
91
        );
92
93
        $adminPassword = $useDefaultConfigParams ? $defaults['admin-password'] : $dialog->askAndValidate(
94
            $this->output,
95
            '<question>Please enter the admin password:</question> <comment>[' .
96
            $defaults['admin-password'] . ']</comment>: ',
97
            $this->notEmptyCallback,
98
            false,
99
            $defaults['admin-password']
100
        );
101
102
        $adminFirstname = $useDefaultConfigParams ? $defaults['admin-firstname'] : $dialog->askAndValidate(
103
            $this->output,
104
            '<question>Please enter the admin\'s firstname:</question> <comment>[' .
105
            $defaults['admin-firstname'] . ']</comment>: ',
106
            $this->notEmptyCallback,
107
            false,
108
            $defaults['admin-firstname']
109
        );
110
111
        $adminLastname = $useDefaultConfigParams ? $defaults['admin-lastname'] : $dialog->askAndValidate(
112
            $this->output,
113
            '<question>Please enter the admin\'s lastname:</question> <comment>[' .
114
            $defaults['admin-lastname'] . ']</comment>: ',
115
            $this->notEmptyCallback,
116
            false,
117
            $defaults['admin-lastname']
118
        );
119
120
        $adminEmail = $useDefaultConfigParams ? $defaults['admin-email'] : $dialog->askAndValidate(
121
            $this->output,
122
            '<question>Please enter the admin\'s email:</question> <comment>[' .
123
            $defaults['admin-email'] . ']</comment>: ',
124
            $this->notEmptyCallback,
125
            false,
126
            $defaults['admin-email']
127
        );
128
129
        $validateBaseUrl = function ($url) {
130
            if (!preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url)) {
131
                throw new \InvalidArgumentException('Please enter a valid URL');
132
            }
133
            if (parse_url($url, \PHP_URL_HOST) == 'localhost') {
134
                throw new \InvalidArgumentException(
135
                    'localhost cause problems! Please use 127.0.0.1 or another hostname'
136
                );
137
            }
138
139
            return $url;
140
        };
141
142
        $baseUrl = ($this->input->getOption('baseUrl') !== null)
143
            ? $this->input->getOption('baseUrl')
144
            : $dialog->askAndValidate(
145
                $this->output,
146
                '<question>Please enter the base url:</question> ',
147
                $validateBaseUrl,
148
                false
149
            );
150
        $baseUrl = rtrim($baseUrl, '/') . '/'; // normalize baseUrl
151
152
        /**
153
         * Correct session save (common mistake)
154
         */
155
        if ($sessionSave == 'file') {
156
            $sessionSave = 'files';
157
        }
158
        $this->_getDefaultSessionFolder($sessionSave);
159
160
        $argv = array(
161
            'language' => $locale,
162
            'timezone' => $timezone,
163
            'db-host' => $this->_prepareDbHost(),
164
            'db-name' => $this->config->getString('db_name'),
165
            'db-user' => $this->config->getString('db_user'),
166
            'base-url' => $baseUrl,
167
            'use-rewrites' => 1,
168
            'use-secure' => 0,
169
            'use-secure-admin' => 1,
170
            'admin-user' => $adminUsername,
171
            'admin-lastname' => $adminLastname,
172
            'admin-firstname' => $adminFirstname,
173
            'admin-email' => $adminEmail,
174
            'admin-password' => $adminPassword,
175
            'session-save' => $sessionSave,
176
            'backend-frontname' => $adminFrontname,
177
            'currency' => $currency,
178
        );
179
180
        $dbPass = $this->config->getString('db_pass');
181
        if (!empty($dbPass)) {
182
            $argv['db-password'] = $dbPass;
183
        }
184
185
        if ($useDefaultConfigParams) {
186
            if (isset($defaults['encryption-key']) && strlen($defaults['encryption-key']) > 0) {
187
                $argv['encryption-key'] = $defaults['encryption-key'];
188
            }
189
            if (strlen($defaults['use-secure']) > 0) {
190
                $argv['use-secure'] = $defaults['use-secure'];
191
                $argv['base-url-secure'] = str_replace('http://', 'https://', $baseUrl);
192
            }
193
            if (strlen($defaults['use-rewrites']) > 0) {
194
                $argv['use-rewrites'] = $defaults['use-rewrites'];
195
            }
196
        }
197
198
        $this->config->setArray('installation_args', $argv);
199
200
        $installArgs = '';
201
        foreach ($argv as $argName => $argValue) {
202
            if (is_null($argValue)) {
203
                $installArgs .= '--' . $argName . ' ';
204
            } elseif (is_bool($argValue)) {
205
                if ($argValue) {
206
                    $argValue = '1';
207
                } else {
208
                    $argValue = '0';
209
                }
210
                $installArgs .= '--' . $argName . '=' . $argValue . ' ';
211
            } else {
212
                $installArgs .= '--' . $argName . '=' . escapeshellarg($argValue) . ' ';
213
            }
214
        }
215
216
        $this->output->writeln('<info>Start installation process.</info>');
217
        $this->_runInstaller($installArgs);
0 ignored issues
show
Documentation introduced by
$installArgs is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
218
    }
219
220
    /**
221
     * @return string
222
     * @throws \Exception
223
     */
224
    protected function getInstallScriptPath()
225
    {
226
        $installerScript = $this->config->getString('installationFolder') . '/bin/magento';
227
        if (!file_exists($installerScript)) {
228
            throw new \RuntimeException('Installation script was not found.', 1);
229
        }
230
231
        return $installerScript;
232
    }
233
234
    /**
235
     * @param $sessionSave
236
     */
237
    protected function _getDefaultSessionFolder($sessionSave)
238
    {
239
        /**
240
         * Try to create session folder
241
         */
242
        $defaultSessionFolder = $this->config->getString('installationFolder') . '/var/session';
243
        if ($sessionSave == 'files' && !is_dir($defaultSessionFolder)) {
244
            @mkdir($defaultSessionFolder);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
245
        }
246
    }
247
248
    /**
249
     * @return string
250
     */
251
    protected function _prepareDbHost()
252
    {
253
        $dbHost = $this->config->getString('db_host');
254
255
        if ($this->config->getInt('db_port') != 3306) {
256
            $dbHost .= ':' . strval($this->config->getInt('db_port'));
257
258
            return $dbHost;
259
        }
260
261
        return $dbHost;
262
    }
263
264
    /**
265
     * @param array $installArgs
266
     *
267
     * @throws \Exception
268
     */
269
    protected function _runInstaller($installArgs)
270
    {
271
        $installationOutput = null;
272
        $returnStatus = null;
273
274
        if (OperatingSystem::isWindows()) {
275
            $installCommand = 'php ' . $this->getInstallScriptPath() . ' setup:install ' . $installArgs;
276
        } else {
277
            $installCommand = '/usr/bin/env php ' . $this->getInstallScriptPath() . ' setup:install ' . $installArgs;
278
        }
279
280
        $this->output->writeln('<comment>' . $installCommand . '</comment>');
281
        exec($installCommand, $installationOutput, $returnStatus);
282
        $installationOutput = implode(PHP_EOL, $installationOutput);
283
        if ($returnStatus !== self::EXEC_STATUS_OK) {
284
            throw new \RuntimeException('Installation failed.' . $installationOutput, 1);
285
        } else {
286
            $this->output->writeln('<info>Successfully installed Magento</info>');
287
            $encryptionKey = trim(substr($installationOutput, strpos($installationOutput, ':') + 1));
288
            $this->output->writeln('<comment>Encryption Key:</comment> <info>' . $encryptionKey . '</info>');
289
        }
290
    }
291
}
292