Completed
Push — master ( 29ee36...92bd35 )
by Tom
03:51
created

InstallMagento::runInstallScriptCommand()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 44
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

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