InstallMagento   B
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 284
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 5
Bugs 2 Features 0
Metric Value
wmc 36
c 5
b 2
f 0
lcom 1
cbo 5
dl 0
loc 284
rs 8.8

5 Methods

Rating   Name   Duplication   Size   Complexity  
F execute() 0 195 26
A getInstallScriptPath() 0 9 2
A _getDefaultSessionFolder() 0 10 3
A _prepareDbHost() 0 12 2
A _runInstaller() 0 22 3
1
<?php
2
3
namespace N98\Magento\Command\Installer\SubCommand;
4
5
use Exception;
6
use N98\Magento\Command\SubCommand\AbstractSubCommand;
7
use N98\Util\OperatingSystem;
8
9
class InstallMagento extends AbstractSubCommand
10
{
11
    /**
12
     * @var int
13
     */
14
    const EXEC_STATUS_OK = 0;
15
16
    /**
17
     * @var \Closure
18
     */
19
    protected $notEmptyCallback;
20
21
    /**
22
     * @return void
23
     * @throws Exception
24
     */
25
    public function execute()
26
    {
27
        $this->notEmptyCallback = function ($input) {
28
            if (empty($input)) {
29
                throw new \InvalidArgumentException('Please enter a value');
30
            }
31
            return $input;
32
        };
33
34
        $this->getCommand()->getApplication()->setAutoExit(false);
35
36
        $dialog = $this->getCommand()->getHelper('dialog');
37
38
        $defaults = $this->commandConfig['installation']['defaults'];
39
40
        $useDefaultConfigParams = $this->getCommand()->parseBoolOption(
41
            $this->input->getOption('useDefaultConfigParams')
42
        );
43
44
        $sessionSave = $useDefaultConfigParams ? $defaults['session-save'] : $dialog->ask(
45
            $this->output,
46
            '<question>Please enter the session save:</question> <comment>[' .
47
            $defaults['session-save'] . ']</comment>: ',
48
            $defaults['session-save']
49
        );
50
51
        $adminFrontname = $useDefaultConfigParams ? $defaults['backend-frontname'] : $dialog->askAndValidate(
52
            $this->output,
53
            '<question>Please enter the admin/backend frontname:</question> <comment>[' .
54
            $defaults['backend-frontname'] . ']</comment> ',
55
            $this->notEmptyCallback,
56
            false,
57
            $defaults['backend-frontname']
58
        );
59
60
        $currency = $useDefaultConfigParams ? $defaults['currency'] : $dialog->askAndValidate(
61
            $this->output,
62
            '<question>Please enter the default currency code:</question> <comment>[' .
63
            $defaults['currency'] . ']</comment>: ',
64
            $this->notEmptyCallback,
65
            false,
66
            $defaults['currency']
67
        );
68
69
        $locale = $useDefaultConfigParams ? $defaults['locale'] : $dialog->askAndValidate(
70
            $this->output,
71
            '<question>Please enter the locale code:</question> <comment>[' . $defaults['locale'] . ']</comment>: ',
72
            $this->notEmptyCallback,
73
            false,
74
            $defaults['locale']
75
        );
76
77
        $timezone = $useDefaultConfigParams ? $defaults['timezone'] : $dialog->askAndValidate(
78
            $this->output,
79
            '<question>Please enter the timezone:</question> <comment>[' . $defaults['timezone'] . ']</comment>: ',
80
            $this->notEmptyCallback,
81
            false,
82
            $defaults['timezone']
83
        );
84
85
        $adminUsername = $useDefaultConfigParams ? $defaults['admin-user'] : $dialog->askAndValidate(
86
            $this->output,
87
            '<question>Please enter the admin username:</question> <comment>[' .
88
            $defaults['admin-user'] . ']</comment>: ',
89
            $this->notEmptyCallback,
90
            false,
91
            $defaults['admin-user']
92
        );
93
94
        $adminPassword = $useDefaultConfigParams ? $defaults['admin-password'] : $dialog->askAndValidate(
95
            $this->output,
96
            '<question>Please enter the admin password:</question> <comment>[' .
97
            $defaults['admin-password'] . ']</comment>: ',
98
            $this->notEmptyCallback,
99
            false,
100
            $defaults['admin-password']
101
        );
102
103
        $adminFirstname = $useDefaultConfigParams ? $defaults['admin-firstname'] : $dialog->askAndValidate(
104
            $this->output,
105
            '<question>Please enter the admin\'s firstname:</question> <comment>[' .
106
            $defaults['admin-firstname'] . ']</comment>: ',
107
            $this->notEmptyCallback,
108
            false,
109
            $defaults['admin-firstname']
110
        );
111
112
        $adminLastname = $useDefaultConfigParams ? $defaults['admin-lastname'] : $dialog->askAndValidate(
113
            $this->output,
114
            '<question>Please enter the admin\'s lastname:</question> <comment>[' .
115
            $defaults['admin-lastname'] . ']</comment>: ',
116
            $this->notEmptyCallback,
117
            false,
118
            $defaults['admin-lastname']
119
        );
120
121
        $adminEmail = $useDefaultConfigParams ? $defaults['admin-email'] : $dialog->askAndValidate(
122
            $this->output,
123
            '<question>Please enter the admin\'s email:</question> <comment>[' .
124
            $defaults['admin-email'] . ']</comment>: ',
125
            $this->notEmptyCallback,
126
            false,
127
            $defaults['admin-email']
128
        );
129
130
        $validateBaseUrl = function ($url) {
131
            if (!preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url)) {
132
                throw new \InvalidArgumentException('Please enter a valid URL');
133
            }
134
            if (parse_url($url, \PHP_URL_HOST) == 'localhost') {
135
                throw new \InvalidArgumentException(
136
                    'localhost cause problems! Please use 127.0.0.1 or another hostname'
137
                );
138
            }
139
140
            return $url;
141
        };
142
143
        $baseUrl = ($this->input->getOption('baseUrl') !== null)
144
            ? $this->input->getOption('baseUrl')
145
            : $dialog->askAndValidate(
146
                $this->output,
147
                '<question>Please enter the base url:</question> ',
148
                $validateBaseUrl,
149
                false
150
            );
151
        $baseUrl = rtrim($baseUrl, '/') . '/'; // normalize baseUrl
152
153
        /**
154
         * Correct session save (common mistake)
155
         */
156
        if ($sessionSave == 'file') {
157
            $sessionSave = 'files';
158
        }
159
        $this->_getDefaultSessionFolder($sessionSave);
160
161
        $argv = array(
162
            'language' => $locale,
163
            'timezone' => $timezone,
164
            'db-host' => $this->_prepareDbHost(),
165
            'db-name' => $this->config->getString('db_name'),
166
            'db-user' => $this->config->getString('db_user'),
167
            'base-url' => $baseUrl,
168
            'use-rewrites' => 1,
169
            'use-secure' => 0,
170
            'use-secure-admin' => 1,
171
            'admin-user' => $adminUsername,
172
            'admin-lastname' => $adminLastname,
173
            'admin-firstname' => $adminFirstname,
174
            'admin-email' => $adminEmail,
175
            'admin-password' => $adminPassword,
176
            'session-save' => $sessionSave,
177
            'backend-frontname' => $adminFrontname,
178
            'currency' => $currency,
179
        );
180
181
        $dbPass = $this->config->getString('db_pass');
182
        if (!empty($dbPass)) {
183
            $argv['db-password'] = $dbPass;
184
        }
185
186
        if ($useDefaultConfigParams) {
187
            if (isset($defaults['encryption-key']) && strlen($defaults['encryption-key']) > 0) {
188
                $argv['encryption-key'] = $defaults['encryption-key'];
189
            }
190
            if (strlen($defaults['use-secure']) > 0) {
191
                $argv['use-secure'] = $defaults['use-secure'];
192
                $argv['base-url-secure'] = str_replace('http://', 'https://', $baseUrl);
193
            }
194
            if (strlen($defaults['use-rewrites']) > 0) {
195
                $argv['use-rewrites'] = $defaults['use-rewrites'];
196
            }
197
        }
198
199
        $this->config->setArray('installation_args', $argv);
200
201
        $installArgs = '';
202
        foreach ($argv as $argName => $argValue) {
203
            if (is_null($argValue)) {
204
                $installArgs .= '--' . $argName . ' ';
205
            } elseif (is_bool($argValue)) {
206
                if ($argValue) {
207
                    $argValue = '1';
208
                } else {
209
                    $argValue = '0';
210
                }
211
                $installArgs .= '--' . $argName . '=' . $argValue . ' ';
212
            } else {
213
                $installArgs .= '--' . $argName . '=' . escapeshellarg($argValue) . ' ';
214
            }
215
        }
216
217
        $this->output->writeln('<info>Start installation process.</info>');
218
        $this->_runInstaller($installArgs);
219
    }
220
221
    /**
222
     * @return string
223
     * @throws Exception
224
     */
225
    protected function getInstallScriptPath()
226
    {
227
        $installerScript = $this->config->getString('installationFolder') . '/bin/magento';
228
        if (!file_exists($installerScript)) {
229
            throw new \RuntimeException('Installation script was not found.', 1);
230
        }
231
232
        return $installerScript;
233
    }
234
235
    /**
236
     * @param $sessionSave
237
     */
238
    protected function _getDefaultSessionFolder($sessionSave)
239
    {
240
        /**
241
         * Try to create session folder
242
         */
243
        $defaultSessionFolder = $this->config->getString('installationFolder') . '/var/session';
244
        if ($sessionSave == 'files' && !is_dir($defaultSessionFolder)) {
245
            @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...
246
        }
247
    }
248
249
    /**
250
     * @return string
251
     */
252
    protected function _prepareDbHost()
253
    {
254
        $dbHost = $this->config->getString('db_host');
255
256
        if ($this->config->getInt('db_port') != 3306) {
257
            $dbHost .= ':' . strval($this->config->getInt('db_port'));
258
259
            return $dbHost;
260
        }
261
262
        return $dbHost;
263
    }
264
265
    /**
266
     * @param string $installArgs
267
     *
268
     * @throws Exception
269
     */
270
    protected function _runInstaller($installArgs)
271
    {
272
        $installationOutput = null;
273
        $returnStatus = null;
274
275
        if (OperatingSystem::isWindows()) {
276
            $installCommand = 'php ' . $this->getInstallScriptPath() . ' setup:install ' . $installArgs;
277
        } else {
278
            $installCommand = '/usr/bin/env php ' . $this->getInstallScriptPath() . ' setup:install ' . $installArgs;
279
        }
280
281
        $this->output->writeln('<comment>' . $installCommand . '</comment>');
282
        exec($installCommand, $installationOutput, $returnStatus);
283
        $installationOutput = implode(PHP_EOL, $installationOutput);
284
        if ($returnStatus !== self::EXEC_STATUS_OK) {
285
            throw new \RuntimeException('Installation failed.' . $installationOutput, 1);
286
        } else {
287
            $this->output->writeln('<info>Successfully installed Magento</info>');
288
            $encryptionKey = trim(substr($installationOutput, strpos($installationOutput, ':') + 1));
289
            $this->output->writeln('<comment>Encryption Key:</comment> <info>' . $encryptionKey . '</info>');
290
        }
291
    }
292
}
293