1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace N98\Magento\Command\Installer; |
4
|
|
|
|
5
|
|
|
use Composer\Composer; |
6
|
|
|
use Composer\Package\CompletePackage; |
7
|
|
|
use Exception; |
8
|
|
|
use InvalidArgumentException; |
9
|
|
|
use N98\Magento\Command\AbstractMagentoCommand; |
10
|
|
|
use N98\Util\BinaryString; |
11
|
|
|
use N98\Util\Database as DatabaseUtils; |
12
|
|
|
use N98\Util\Exec; |
13
|
|
|
use N98\Util\Filesystem; |
14
|
|
|
use N98\Util\OperatingSystem; |
15
|
|
|
use N98\Util\VerifyOrDie; |
16
|
|
|
use PDO; |
17
|
|
|
use PDOException; |
18
|
|
|
use RuntimeException; |
19
|
|
|
use Symfony\Component\Console\Helper\DialogHelper; |
20
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
21
|
|
|
use Symfony\Component\Console\Input\InputOption; |
22
|
|
|
use Symfony\Component\Console\Input\StringInput; |
23
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
24
|
|
|
use Symfony\Component\Finder\Finder; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Class InstallCommand |
28
|
|
|
* |
29
|
|
|
* @codeCoverageIgnore - Travis server uses installer to create a new shop. If it not works complete build fails. |
30
|
|
|
* @package N98\Magento\Command\Installer |
31
|
|
|
*/ |
32
|
|
|
class InstallCommand extends AbstractMagentoCommand |
33
|
|
|
{ |
34
|
|
|
/** |
35
|
|
|
* @deprecated since since 1.97.22; Use constant from Exec-Utility instead |
36
|
|
|
* @see Exec::CODE_CLEAN_EXIT |
37
|
|
|
*/ |
38
|
|
|
const EXEC_STATUS_OK = 0; |
39
|
|
|
|
40
|
|
|
const DEFAULT_SESSION_PATH = 'var/session'; |
41
|
|
|
|
42
|
|
|
const MAGENTO_INSTALL_SCRIPT_PATH = 'install.php'; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @var array |
46
|
|
|
*/ |
47
|
|
|
protected $config; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @var array |
51
|
|
|
*/ |
52
|
|
|
protected $_argv; |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* @var array |
56
|
|
|
*/ |
57
|
|
|
protected $commandConfig; |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @var \Closure |
61
|
|
|
*/ |
62
|
|
|
protected $notEmptyCallback; |
63
|
|
|
|
64
|
|
|
protected function configure() |
65
|
|
|
{ |
66
|
|
|
$this |
67
|
|
|
->setName('install') |
68
|
|
|
->addOption('magentoVersion', null, InputOption::VALUE_OPTIONAL, 'Magento version') |
69
|
|
|
->addOption( |
70
|
|
|
'magentoVersionByName', |
71
|
|
|
null, |
72
|
|
|
InputOption::VALUE_OPTIONAL, |
73
|
|
|
'Magento version name instead of order number' |
74
|
|
|
) |
75
|
|
|
->addOption('installationFolder', null, InputOption::VALUE_OPTIONAL, 'Installation folder') |
76
|
|
|
->addOption('dbHost', null, InputOption::VALUE_OPTIONAL, 'Database host') |
77
|
|
|
->addOption('dbUser', null, InputOption::VALUE_OPTIONAL, 'Database user') |
78
|
|
|
->addOption('dbPass', null, InputOption::VALUE_OPTIONAL, 'Database password') |
79
|
|
|
->addOption('dbName', null, InputOption::VALUE_OPTIONAL, 'Database name') |
80
|
|
|
->addOption('dbPort', null, InputOption::VALUE_OPTIONAL, 'Database port', 3306) |
81
|
|
|
->addOption('dbPrefix', null, InputOption::VALUE_OPTIONAL, 'Table prefix', '') |
82
|
|
|
->addOption('installSampleData', null, InputOption::VALUE_OPTIONAL, 'Install sample data') |
83
|
|
|
->addOption( |
84
|
|
|
'useDefaultConfigParams', |
85
|
|
|
null, |
86
|
|
|
InputOption::VALUE_OPTIONAL, |
87
|
|
|
'Use default installation parameters defined in the yaml file' |
88
|
|
|
)->addOption('baseUrl', null, InputOption::VALUE_OPTIONAL, 'Installation base url') |
89
|
|
|
->addOption( |
90
|
|
|
'replaceHtaccessFile', |
91
|
|
|
null, |
92
|
|
|
InputOption::VALUE_OPTIONAL, |
93
|
|
|
'Generate htaccess file (for non vhost environment)' |
94
|
|
|
)->addOption( |
95
|
|
|
'noDownload', |
96
|
|
|
null, |
97
|
|
|
InputOption::VALUE_NONE, |
98
|
|
|
'If set skips download step. Used when installationFolder is already a Magento installation that has ' . |
99
|
|
|
'to be installed on the given database.' |
100
|
|
|
) |
101
|
|
|
->addOption( |
102
|
|
|
'only-download', |
103
|
|
|
null, |
104
|
|
|
InputOption::VALUE_NONE, |
105
|
|
|
'Downloads (and extracts) source code' |
106
|
|
|
) |
107
|
|
|
->addOption( |
108
|
|
|
'forceUseDb', |
109
|
|
|
null, |
110
|
|
|
InputOption::VALUE_NONE, |
111
|
|
|
'If --noDownload passed, force to use given database if it already exists.' |
112
|
|
|
)->setDescription('Install magento'); |
113
|
|
|
|
114
|
|
|
$help = <<<HELP |
115
|
|
|
* Download Magento by a list of git repos and zip files (mageplus, |
116
|
|
|
magelte, official community packages). |
117
|
|
|
* Try to create database if it does not exist. |
118
|
|
|
* Installs Magento sample data if available (since version 1.2.0). |
119
|
|
|
* Starts Magento installer |
120
|
|
|
* Sets rewrite base in .htaccess file |
121
|
|
|
|
122
|
|
|
Example of an unattended Magento CE 1.7.0.2 installation: |
123
|
|
|
|
124
|
|
|
$ n98-magerun.phar install --dbHost="localhost" --dbUser="mydbuser" \ |
125
|
|
|
--dbPass="mysecret" --dbName="magentodb" --installSampleData=yes \ |
126
|
|
|
--useDefaultConfigParams=yes \ |
127
|
|
|
--magentoVersionByName="magento-ce-1.7.0.2" \ |
128
|
|
|
--installationFolder="magento" --baseUrl="http://magento.localdomain/" |
129
|
|
|
|
130
|
|
|
Additionally, with --noDownload option you can install Magento working |
131
|
|
|
copy already stored in --installationFolder on the given database. |
132
|
|
|
|
133
|
|
|
See it in action: http://youtu.be/WU-CbJ86eQc |
134
|
|
|
|
135
|
|
|
HELP; |
136
|
|
|
$this->setHelp($help); |
137
|
|
|
|
138
|
|
|
$this->notEmptyCallback = function ($input) { |
139
|
|
|
if (empty($input)) { |
140
|
|
|
throw new InvalidArgumentException('Please enter a value'); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
return $input; |
144
|
|
|
}; |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* @return bool |
149
|
|
|
*/ |
150
|
|
|
public function isEnabled() |
151
|
|
|
{ |
152
|
|
|
return Exec::allowed(); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* @param InputInterface $input |
157
|
|
|
* @param OutputInterface $output |
158
|
|
|
* @throws RuntimeException |
159
|
|
|
* @return int|null|void |
160
|
|
|
*/ |
161
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
162
|
|
|
{ |
163
|
|
|
$this->commandConfig = $this->getCommandConfig(); |
164
|
|
|
$this->writeSection($output, 'Magento Installation'); |
165
|
|
|
|
166
|
|
|
$this->precheckPhp(); |
167
|
|
|
|
168
|
|
|
if (!$input->getOption('noDownload')) { |
169
|
|
|
$this->selectMagentoVersion($input, $output); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
$this->chooseInstallationFolder($input, $output); |
173
|
|
|
|
174
|
|
|
if (!$input->getOption('noDownload')) { |
175
|
|
|
$result = $this->downloadMagento($input, $output); |
176
|
|
|
|
177
|
|
|
if ($result === false) { |
178
|
|
|
return 1; |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
if ($input->getOption('only-download')) { |
183
|
|
|
return 0; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
$this->createDatabase($input, $output); |
187
|
|
|
|
188
|
|
|
if (!$input->getOption('noDownload')) { |
189
|
|
|
$this->installSampleData($input, $output); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
$this->removeEmptyFolders(); |
193
|
|
|
$this->setDirectoryPermissions($output); |
194
|
|
|
$this->installMagento($input, $output, $this->config['installationFolder']); |
|
|
|
|
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* Check PHP environment agains minimal required settings modules |
199
|
|
|
*/ |
200
|
|
|
protected function precheckPhp() |
201
|
|
|
{ |
202
|
|
|
$extensions = $this->commandConfig['installation']['pre-check']['php']['extensions']; |
203
|
|
|
$missingExtensions = array(); |
204
|
|
|
foreach ($extensions as $extension) { |
205
|
|
|
if (!extension_loaded($extension)) { |
206
|
|
|
$missingExtensions[] = $extension; |
207
|
|
|
} |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
if (count($missingExtensions) > 0) { |
211
|
|
|
throw new RuntimeException( |
212
|
|
|
'The following PHP extensions are required to start installation: ' . implode(',', $missingExtensions) |
213
|
|
|
); |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @param InputInterface $input |
219
|
|
|
* @param OutputInterface $output |
220
|
|
|
* |
221
|
|
|
* @throws InvalidArgumentException |
222
|
|
|
*/ |
223
|
|
|
protected function selectMagentoVersion(InputInterface $input, OutputInterface $output) |
224
|
|
|
{ |
225
|
|
|
if ($input->getOption('magentoVersion') == null && $input->getOption('magentoVersionByName') == null) { |
226
|
|
|
$question = array(); |
227
|
|
|
foreach ($this->commandConfig['magento-packages'] as $key => $package) { |
228
|
|
|
$question[] = '<comment>' . str_pad('[' . ($key + 1) . ']', 4, ' ') . '</comment> ' . |
229
|
|
|
$package['name'] . "\n"; |
230
|
|
|
} |
231
|
|
|
$question[] = "<question>Choose a magento version:</question> "; |
232
|
|
|
|
233
|
|
|
$commandConfig = $this->commandConfig; |
234
|
|
|
|
235
|
|
|
$type = $this->getHelper('dialog')->askAndValidate( |
236
|
|
|
$output, |
237
|
|
|
$question, |
238
|
|
|
function ($typeInput) use ($commandConfig) { |
239
|
|
|
if (!in_array($typeInput, range(1, count($commandConfig['magento-packages'])))) { |
240
|
|
|
throw new InvalidArgumentException('Invalid type'); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
return $typeInput; |
244
|
|
|
} |
245
|
|
|
); |
246
|
|
|
} else { |
247
|
|
|
$type = null; |
248
|
|
|
|
249
|
|
|
if ($input->getOption('magentoVersion')) { |
250
|
|
|
$type = $input->getOption('magentoVersion'); |
251
|
|
|
if ($type !== (string) (int) $type) { |
252
|
|
|
$type = $this->getPackageNumberByName($type); |
253
|
|
|
} |
254
|
|
|
} elseif ($input->getOption('magentoVersionByName')) { |
255
|
|
|
$type = $this->getPackageNumberByName($input->getOption('magentoVersionByName')); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
if ($type == null) { |
259
|
|
|
throw new InvalidArgumentException('Unable to locate Magento version'); |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
$magentoPackages = $this->commandConfig['magento-packages']; |
264
|
|
|
|
265
|
|
|
$index = $type - 1; |
266
|
|
|
if (!isset($magentoPackages[$index])) { |
267
|
|
|
throw new InvalidArgumentException( |
268
|
|
|
sprintf( |
269
|
|
|
'Invalid Magento package number %s, must be from 1 to %d.', |
270
|
|
|
var_export($type, true), |
271
|
|
|
count($magentoPackages) |
272
|
|
|
) |
273
|
|
|
); |
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
$this->config['magentoVersionData'] = $magentoPackages[$index]; |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
/** |
280
|
|
|
* @param $name |
281
|
|
|
* |
282
|
|
|
* @return int 1 or greater as the one-based package number, null on failure to resolve the name |
283
|
|
|
*/ |
284
|
|
|
private function getPackageNumberByName($name) |
285
|
|
|
{ |
286
|
|
|
// directly filter integer strings |
287
|
|
|
if ($name === (string) (int) $name) { |
288
|
|
|
return (int) $name; |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
$magentoPackages = $this->commandConfig['magento-packages']; |
292
|
|
|
|
293
|
|
|
foreach ($magentoPackages as $key => $package) { |
294
|
|
|
if ($package['name'] === $name) { |
295
|
|
|
return $key + 1; |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
return; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* @param InputInterface $input |
304
|
|
|
* @param OutputInterface $output |
305
|
|
|
* @return bool |
306
|
|
|
*/ |
307
|
|
|
public function downloadMagento(InputInterface $input, OutputInterface $output) |
308
|
|
|
{ |
309
|
|
|
try { |
310
|
|
|
$package = $this->createComposerPackageByConfig($this->config['magentoVersionData']); |
311
|
|
|
$this->config['magentoPackage'] = $package; |
312
|
|
|
|
313
|
|
|
if (file_exists($this->config['installationFolder'] . '/app/Mage.php')) { |
314
|
|
|
$output->writeln('<error>A magento installation already exists in this folder </error>'); |
315
|
|
|
|
316
|
|
|
return false; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
$composer = $this->getComposer($input, $output); |
320
|
|
|
$targetFolder = $this->getTargetFolderByType($composer, $package, $this->config['installationFolder']); |
321
|
|
|
$this->config['magentoPackage'] = $this->downloadByComposerConfig( |
322
|
|
|
$input, |
323
|
|
|
$output, |
324
|
|
|
$package, |
325
|
|
|
$targetFolder, |
326
|
|
|
true |
327
|
|
|
); |
328
|
|
|
|
329
|
|
|
if ($this->isSourceTypeRepository($package->getSourceType())) { |
330
|
|
|
$filesystem = new \N98\Util\Filesystem; |
331
|
|
|
$filesystem->recursiveCopy($targetFolder, $this->config['installationFolder'], array('.git', '.hg')); |
332
|
|
|
} else { |
333
|
|
|
$filesystem = new \Composer\Util\Filesystem(); |
334
|
|
|
$filesystem->copyThenRemove( |
335
|
|
|
$this->config['installationFolder'] . '/_n98_magerun_download', |
336
|
|
|
$this->config['installationFolder'] |
337
|
|
|
); |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
if (version_compare(PHP_VERSION, '5.4.0') >= 0) { |
341
|
|
|
// Patch installer |
342
|
|
|
$this->patchMagentoInstallerForPHP54($this->config['installationFolder']); |
343
|
|
|
} |
344
|
|
|
} catch (Exception $e) { |
345
|
|
|
$output->writeln('<error>' . $e->getMessage() . '</error>'); |
346
|
|
|
|
347
|
|
|
return false; |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
return true; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
/** |
354
|
|
|
* construct a folder to where magerun will download the source to, cache git/hg repositories under COMPOSER_HOME |
355
|
|
|
* |
356
|
|
|
* @param Composer $composer |
357
|
|
|
* @param CompletePackage $package |
358
|
|
|
* @param $installationFolder |
359
|
|
|
* |
360
|
|
|
* @return string |
361
|
|
|
*/ |
362
|
|
|
protected function getTargetFolderByType(Composer $composer, CompletePackage $package, $installationFolder) |
363
|
|
|
{ |
364
|
|
|
$type = $package->getSourceType(); |
365
|
|
|
if ($this->isSourceTypeRepository($type)) { |
366
|
|
|
$targetPath = sprintf( |
367
|
|
|
'%s/%s/%s/%s', |
368
|
|
|
$composer->getConfig()->get('cache-dir'), |
369
|
|
|
'_n98_magerun_download', |
370
|
|
|
$type, |
371
|
|
|
preg_replace('{[^a-z0-9.]}i', '-', $package->getSourceUrl()) |
372
|
|
|
); |
373
|
|
|
} else { |
374
|
|
|
$targetPath = sprintf( |
375
|
|
|
'%s/%s', |
376
|
|
|
$installationFolder, |
377
|
|
|
'_n98_magerun_download' |
378
|
|
|
); |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
return $targetPath; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* @param string $magentoFolder |
386
|
|
|
*/ |
387
|
|
|
protected function patchMagentoInstallerForPHP54($magentoFolder) |
388
|
|
|
{ |
389
|
|
|
$installerConfig = $magentoFolder |
390
|
|
|
. DIRECTORY_SEPARATOR |
391
|
|
|
. 'app/code/core/Mage/Install/etc/config.xml'; |
392
|
|
|
if (file_exists($installerConfig)) { |
393
|
|
|
$xml = file_get_contents($installerConfig); |
394
|
|
|
file_put_contents($installerConfig, str_replace('<pdo_mysql/>', '<pdo_mysql>1</pdo_mysql>', $xml)); |
395
|
|
|
} |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
/** |
399
|
|
|
* @param InputInterface $input |
400
|
|
|
* @param OutputInterface $output |
401
|
|
|
* |
402
|
|
|
* @throws InvalidArgumentException |
403
|
|
|
*/ |
404
|
|
|
protected function createDatabase(InputInterface $input, OutputInterface $output) |
405
|
|
|
{ |
406
|
|
|
$dbOptions = array('--dbHost', '--dbUser', '--dbPass', '--dbName'); |
407
|
|
|
$dbOptionsFound = 0; |
408
|
|
|
foreach ($dbOptions as $dbOption) { |
409
|
|
|
foreach ($this->getCliArguments() as $definedCliOption) { |
410
|
|
|
if (BinaryString::startsWith($definedCliOption, $dbOption)) { |
411
|
|
|
$dbOptionsFound++; |
412
|
|
|
} |
413
|
|
|
} |
414
|
|
|
} |
415
|
|
|
|
416
|
|
|
$hasAllOptions = $dbOptionsFound == 4; |
417
|
|
|
|
418
|
|
|
// if all database options were passed in at cmd line |
419
|
|
|
if ($hasAllOptions) { |
420
|
|
|
$this->config['db_host'] = $input->getOption('dbHost'); |
421
|
|
|
$this->config['db_user'] = $input->getOption('dbUser'); |
422
|
|
|
$this->config['db_pass'] = $input->getOption('dbPass'); |
423
|
|
|
$this->config['db_name'] = VerifyOrDie::filename( |
424
|
|
|
$input->getOption('dbName'), |
425
|
|
|
'Database name is not portable' |
426
|
|
|
); |
427
|
|
|
$this->config['db_port'] = $input->getOption('dbPort'); |
428
|
|
|
$this->config['db_prefix'] = $input->getOption('dbPrefix'); |
429
|
|
|
$db = $this->validateDatabaseSettings($output, $input); |
430
|
|
|
|
431
|
|
|
if ($db === false) { |
432
|
|
|
throw new InvalidArgumentException("Database configuration is invalid"); |
433
|
|
|
} |
434
|
|
|
} else { |
435
|
|
|
/** @var DialogHelper $dialog */ |
436
|
|
|
$dialog = $this->getHelper('dialog'); |
437
|
|
|
do { |
438
|
|
|
$dbHostDefault = $input->getOption('dbHost') ? $input->getOption('dbHost') : 'localhost'; |
439
|
|
|
$this->config['db_host'] = $dialog->askAndValidate( |
440
|
|
|
$output, |
441
|
|
|
'<question>Please enter the database host</question> <comment>[' . $dbHostDefault . ']</comment>: ', |
442
|
|
|
$this->notEmptyCallback, |
443
|
|
|
false, |
444
|
|
|
$dbHostDefault |
445
|
|
|
); |
446
|
|
|
|
447
|
|
|
$dbUserDefault = $input->getOption('dbUser') ? $input->getOption('dbUser') : 'root'; |
448
|
|
|
$this->config['db_user'] = $dialog->askAndValidate( |
449
|
|
|
$output, |
450
|
|
|
'<question>Please enter the database username</question> <comment>[' . $dbUserDefault . |
451
|
|
|
']</comment>: ', |
452
|
|
|
$this->notEmptyCallback, |
453
|
|
|
false, |
454
|
|
|
$dbUserDefault |
455
|
|
|
); |
456
|
|
|
|
457
|
|
|
$dbPassDefault = $input->getOption('dbPass') ? $input->getOption('dbPass') : ''; |
458
|
|
|
$this->config['db_pass'] = $dialog->ask( |
459
|
|
|
$output, |
460
|
|
|
'<question>Please enter the database password</question> <comment>[' . $dbPassDefault . |
461
|
|
|
']</comment>: ', |
462
|
|
|
$dbPassDefault |
463
|
|
|
); |
464
|
|
|
|
465
|
|
|
$dbNameDefault = $input->getOption('dbName') ? $input->getOption('dbName') : 'magento'; |
466
|
|
|
$this->config['db_name'] = $dialog->askAndValidate( |
467
|
|
|
$output, |
468
|
|
|
'<question>Please enter the database name</question> <comment>[' . $dbNameDefault . ']</comment>: ', |
469
|
|
|
$this->notEmptyCallback, |
470
|
|
|
false, |
471
|
|
|
$dbNameDefault |
472
|
|
|
); |
473
|
|
|
|
474
|
|
|
$dbPortDefault = $input->getOption('dbPort') ? $input->getOption('dbPort') : 3306; |
475
|
|
|
$this->config['db_port'] = $dialog->askAndValidate( |
476
|
|
|
$output, |
477
|
|
|
'<question>Please enter the database port </question> <comment>[' . $dbPortDefault . |
478
|
|
|
']</comment>: ', |
479
|
|
|
$this->notEmptyCallback, |
480
|
|
|
false, |
481
|
|
|
$dbPortDefault |
482
|
|
|
); |
483
|
|
|
|
484
|
|
|
$dbPrefixDefault = $input->getOption('dbPrefix') ? $input->getOption('dbPrefix') : ''; |
485
|
|
|
$this->config['db_prefix'] = $dialog->ask( |
486
|
|
|
$output, |
487
|
|
|
'<question>Please enter the table prefix</question> <comment>[' . $dbPrefixDefault . ']</comment>:', |
488
|
|
|
$dbPrefixDefault |
489
|
|
|
); |
490
|
|
|
$db = $this->validateDatabaseSettings($output, $input); |
491
|
|
|
} while ($db === false); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
$this->config['db'] = $db; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* @param OutputInterface $output |
499
|
|
|
* @param InputInterface $input |
500
|
|
|
* |
501
|
|
|
* @return bool|PDO |
502
|
|
|
*/ |
503
|
|
|
protected function validateDatabaseSettings(OutputInterface $output, InputInterface $input) |
504
|
|
|
{ |
505
|
|
|
try { |
506
|
|
|
$dsn = sprintf("mysql:host=%s;port=%s", $this->config['db_host'], $this->config['db_port']); |
507
|
|
|
$db = new PDO($dsn, $this->config['db_user'], $this->config['db_pass']); |
508
|
|
|
if (!$db->query('USE ' . $this->config['db_name'])) { |
509
|
|
|
$db->query("CREATE DATABASE `" . $this->config['db_name'] . "`"); |
510
|
|
|
$output->writeln('<info>Created database ' . $this->config['db_name'] . '</info>'); |
511
|
|
|
$db->query('USE ' . $this->config['db_name']); |
512
|
|
|
|
513
|
|
|
return $db; |
514
|
|
|
} |
515
|
|
|
} catch (PDOException $e) { |
516
|
|
|
$output->writeln('<error>' . $e->getMessage() . '</error>'); |
517
|
|
|
return false; |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
if ($input->getOption('noDownload') && !$input->getOption('forceUseDb')) { |
521
|
|
|
$output->writeln( |
522
|
|
|
sprintf( |
523
|
|
|
"<error>Database '%s' already exists, use --forceUseDb in combination with --noDownload" . |
524
|
|
|
" to use an existing database</error>", |
525
|
|
|
$this->config['db_name'] |
526
|
|
|
) |
527
|
|
|
); |
528
|
|
|
return false; |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
return $db; |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
/** |
535
|
|
|
* @param InputInterface $input |
536
|
|
|
* @param OutputInterface $output |
537
|
|
|
*/ |
538
|
|
|
protected function installSampleData(InputInterface $input, OutputInterface $output) |
539
|
|
|
{ |
540
|
|
|
$magentoPackage = $this->config['magentoPackage']; |
541
|
|
|
/* @var $magentoPackage \Composer\Package\MemoryPackage */ |
542
|
|
|
$extra = $magentoPackage->getExtra(); |
543
|
|
|
if (!isset($extra['sample-data'])) { |
544
|
|
|
return; |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
$dialog = $this->getHelper('dialog'); |
548
|
|
|
|
549
|
|
|
$installSampleData = ($input->getOption('installSampleData') !== null) |
550
|
|
|
? $this->_parseBoolOption($input->getOption('installSampleData')) |
551
|
|
|
: $dialog->askConfirmation( |
552
|
|
|
$output, |
553
|
|
|
'<question>Install sample data?</question> <comment>[y]</comment>: ' |
554
|
|
|
); |
555
|
|
|
|
556
|
|
|
if ($installSampleData) { |
557
|
|
|
$filesystem = new Filesystem(); |
558
|
|
|
|
559
|
|
|
foreach ($this->commandConfig['demo-data-packages'] as $demoPackageData) { |
560
|
|
|
if ($demoPackageData['name'] == $extra['sample-data']) { |
561
|
|
|
$package = $this->downloadByComposerConfig( |
562
|
|
|
$input, |
563
|
|
|
$output, |
564
|
|
|
$demoPackageData, |
565
|
|
|
$this->config['installationFolder'] . '/_temp_demo_data', |
566
|
|
|
false |
567
|
|
|
); |
568
|
|
|
|
569
|
|
|
$this->_fixComposerExtractionBug(); |
570
|
|
|
|
571
|
|
|
$expandedFolder = $this->config['installationFolder'] |
572
|
|
|
. '/_temp_demo_data/' |
573
|
|
|
. str_replace(array('.tar.gz', '.tar.bz2', '.zip'), '', basename($package->getDistUrl())); |
574
|
|
|
if (is_dir($expandedFolder)) { |
575
|
|
|
$filesystem->recursiveCopy( |
576
|
|
|
$expandedFolder, |
577
|
|
|
$this->config['installationFolder'] |
578
|
|
|
); |
579
|
|
|
$filesystem->recursiveRemoveDirectory($expandedFolder); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
// Remove empty folder |
583
|
|
View Code Duplication |
if (is_dir($this->config['installationFolder'] . '/vendor/composer')) { |
|
|
|
|
584
|
|
|
$filesystem->recursiveRemoveDirectory($this->config['installationFolder'] . '/vendor/composer'); |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
// Install sample data |
588
|
|
|
$sampleDataSqlFile = glob( |
589
|
|
|
$this->config['installationFolder'] . '/_temp_demo_data/magento_*sample_data*sql' |
590
|
|
|
); |
591
|
|
|
$db = $this->config['db']; |
592
|
|
|
/* @var $db PDO */ |
593
|
|
|
if (isset($sampleDataSqlFile[0])) { |
594
|
|
|
if (OperatingSystem::isProgramInstalled('mysql')) { |
595
|
|
|
$exec = 'mysql ' |
596
|
|
|
. '-h' . escapeshellarg(strval($this->config['db_host'])) |
597
|
|
|
. ' ' |
598
|
|
|
. '-u' . escapeshellarg(strval($this->config['db_user'])) |
599
|
|
|
. ' ' |
600
|
|
|
. ($this->config['db_port'] != '3306' |
601
|
|
|
? '-P' . escapeshellarg($this->config['db_port']) . ' ' : '') |
602
|
|
|
. (!strval($this->config['db_pass'] == '') |
603
|
|
|
? '-p' . escapeshellarg($this->config['db_pass']) . ' ' : '') |
604
|
|
|
. strval($this->config['db_name']) |
605
|
|
|
. ' < ' |
606
|
|
|
. escapeshellarg($sampleDataSqlFile[0]); |
607
|
|
|
$output->writeln( |
608
|
|
|
'<info>Importing <comment>' . $sampleDataSqlFile[0] . |
609
|
|
|
'</comment> with mysql cli client</info>' |
610
|
|
|
); |
611
|
|
|
Exec::run($exec); |
612
|
|
|
@unlink($sampleDataSqlFile[0]); |
|
|
|
|
613
|
|
|
} else { |
614
|
|
|
$output->writeln( |
615
|
|
|
'<info>Importing <comment>' . $sampleDataSqlFile[0] . |
616
|
|
|
'</comment> with PDO driver</info>' |
617
|
|
|
); |
618
|
|
|
// Fallback -> Try to install dump file by PDO driver |
619
|
|
|
$dbUtils = new DatabaseUtils(); |
620
|
|
|
$dbUtils->importSqlDump($db, $sampleDataSqlFile[0]); |
621
|
|
|
} |
622
|
|
|
} |
623
|
|
|
} |
624
|
|
|
} |
625
|
|
|
|
626
|
|
View Code Duplication |
if (is_dir($this->config['installationFolder'] . '/_temp_demo_data')) { |
|
|
|
|
627
|
|
|
$filesystem->recursiveRemoveDirectory($this->config['installationFolder'] . '/_temp_demo_data'); |
628
|
|
|
} |
629
|
|
|
} |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
protected function _fixComposerExtractionBug() |
633
|
|
|
{ |
634
|
|
|
$filesystem = new Filesystem(); |
635
|
|
|
foreach (array('/_temp_demo_data/media' => '/media', '/_temp_demo_data/skin' => '/skin') as $wrong => $right) { |
636
|
|
|
$wrongFolder = $this->config['installationFolder'] . $wrong; |
637
|
|
|
$rightFolder = $this->config['installationFolder'] . $right; |
638
|
|
|
if (is_dir($wrongFolder)) { |
639
|
|
|
$filesystem->recursiveCopy( |
640
|
|
|
$wrongFolder, |
641
|
|
|
$rightFolder |
642
|
|
|
); |
643
|
|
|
$filesystem->recursiveRemoveDirectory($wrongFolder); |
644
|
|
|
} |
645
|
|
|
} |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
/** |
649
|
|
|
* Remove empty composer extraction folder |
650
|
|
|
*/ |
651
|
|
|
protected function removeEmptyFolders() |
652
|
|
|
{ |
653
|
|
|
if (is_dir(getcwd() . '/vendor')) { |
654
|
|
|
$finder = new Finder(); |
655
|
|
|
$finder->files()->depth(3)->in(getcwd() . '/vendor'); |
656
|
|
|
if ($finder->count() == 0) { |
657
|
|
|
$filesystem = new Filesystem(); |
658
|
|
|
$filesystem->recursiveRemoveDirectory(getcwd() . '/vendor'); |
659
|
|
|
} |
660
|
|
|
} |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
/** |
664
|
|
|
* @param InputInterface $input |
665
|
|
|
* @param OutputInterface $output |
666
|
|
|
* |
667
|
|
|
* @return array |
668
|
|
|
* @throws InvalidArgumentException parameter mismatch (e.g. base-url components like hostname) |
669
|
|
|
* @throws RuntimeException |
670
|
|
|
*/ |
671
|
|
|
protected function installMagento(InputInterface $input, OutputInterface $output) |
672
|
|
|
{ |
673
|
|
|
$this->getApplication()->setAutoExit(false); |
674
|
|
|
/** @var $dialog \Symfony\Component\Console\Helper\DialogHelper */ |
675
|
|
|
$dialog = $this->getHelper('dialog'); |
676
|
|
|
|
677
|
|
|
$defaults = $this->commandConfig['installation']['defaults']; |
678
|
|
|
|
679
|
|
|
$useDefaultConfigParams = $this->_parseBoolOption($input->getOption('useDefaultConfigParams')); |
680
|
|
|
|
681
|
|
|
$sessionSave = $useDefaultConfigParams ? $defaults['session_save'] : $dialog->ask( |
682
|
|
|
$output, |
683
|
|
|
'<question>Please enter the session save:</question> <comment>[' . |
684
|
|
|
$defaults['session_save'] . ']</comment>: ', |
685
|
|
|
$defaults['session_save'] |
686
|
|
|
); |
687
|
|
|
|
688
|
|
|
$adminFrontname = $useDefaultConfigParams ? $defaults['admin_frontname'] : $dialog->askAndValidate( |
689
|
|
|
$output, |
690
|
|
|
'<question>Please enter the admin frontname:</question> <comment>[' . |
691
|
|
|
$defaults['admin_frontname'] . ']</comment> ', |
692
|
|
|
$this->notEmptyCallback, |
693
|
|
|
false, |
694
|
|
|
$defaults['admin_frontname'] |
695
|
|
|
); |
696
|
|
|
|
697
|
|
|
$currency = $useDefaultConfigParams ? $defaults['currency'] : $dialog->askAndValidate( |
698
|
|
|
$output, |
699
|
|
|
'<question>Please enter the default currency code:</question> <comment>[' . |
700
|
|
|
$defaults['currency'] . ']</comment>: ', |
701
|
|
|
$this->notEmptyCallback, |
702
|
|
|
false, |
703
|
|
|
$defaults['currency'] |
704
|
|
|
); |
705
|
|
|
|
706
|
|
|
$locale = $useDefaultConfigParams ? $defaults['locale'] : $dialog->askAndValidate( |
707
|
|
|
$output, |
708
|
|
|
'<question>Please enter the locale code:</question> <comment>[' . $defaults['locale'] . ']</comment>: ', |
709
|
|
|
$this->notEmptyCallback, |
710
|
|
|
false, |
711
|
|
|
$defaults['locale'] |
712
|
|
|
); |
713
|
|
|
|
714
|
|
|
$timezone = $useDefaultConfigParams ? $defaults['timezone'] : $dialog->askAndValidate( |
715
|
|
|
$output, |
716
|
|
|
'<question>Please enter the timezone:</question> <comment>[' . $defaults['timezone'] . ']</comment>: ', |
717
|
|
|
$this->notEmptyCallback, |
718
|
|
|
false, |
719
|
|
|
$defaults['timezone'] |
720
|
|
|
); |
721
|
|
|
|
722
|
|
|
$adminUsername = $useDefaultConfigParams ? $defaults['admin_username'] : $dialog->askAndValidate( |
723
|
|
|
$output, |
724
|
|
|
'<question>Please enter the admin username:</question> <comment>[' . |
725
|
|
|
$defaults['admin_username'] . ']</comment>: ', |
726
|
|
|
$this->notEmptyCallback, |
727
|
|
|
false, |
728
|
|
|
$defaults['admin_username'] |
729
|
|
|
); |
730
|
|
|
|
731
|
|
|
$adminPassword = $useDefaultConfigParams ? $defaults['admin_password'] : $dialog->askAndValidate( |
732
|
|
|
$output, |
733
|
|
|
'<question>Please enter the admin password:</question> <comment>[' . |
734
|
|
|
$defaults['admin_password'] . ']</comment>: ', |
735
|
|
|
$this->notEmptyCallback, |
736
|
|
|
false, |
737
|
|
|
$defaults['admin_password'] |
738
|
|
|
); |
739
|
|
|
|
740
|
|
|
$adminFirstname = $useDefaultConfigParams ? $defaults['admin_firstname'] : $dialog->askAndValidate( |
741
|
|
|
$output, |
742
|
|
|
'<question>Please enter the admin\'s firstname:</question> <comment>[' . |
743
|
|
|
$defaults['admin_firstname'] . ']</comment>: ', |
744
|
|
|
$this->notEmptyCallback, |
745
|
|
|
false, |
746
|
|
|
$defaults['admin_firstname'] |
747
|
|
|
); |
748
|
|
|
|
749
|
|
|
$adminLastname = $useDefaultConfigParams ? $defaults['admin_lastname'] : $dialog->askAndValidate( |
750
|
|
|
$output, |
751
|
|
|
'<question>Please enter the admin\'s lastname:</question> <comment>[' . |
752
|
|
|
$defaults['admin_lastname'] . ']</comment>: ', |
753
|
|
|
$this->notEmptyCallback, |
754
|
|
|
false, |
755
|
|
|
$defaults['admin_lastname'] |
756
|
|
|
); |
757
|
|
|
|
758
|
|
|
$adminEmail = $useDefaultConfigParams ? $defaults['admin_email'] : $dialog->askAndValidate( |
759
|
|
|
$output, |
760
|
|
|
'<question>Please enter the admin\'s email:</question> <comment>[' . |
761
|
|
|
$defaults['admin_email'] . ']</comment>: ', |
762
|
|
|
$this->notEmptyCallback, |
763
|
|
|
false, |
764
|
|
|
$defaults['admin_email'] |
765
|
|
|
); |
766
|
|
|
|
767
|
|
|
$validateBaseUrl = function ($input) { |
768
|
|
|
if (!preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $input)) { |
769
|
|
|
throw new InvalidArgumentException( |
770
|
|
|
sprintf('Invalid URL %s. Please enter a valid URL', var_export($input, true)) |
771
|
|
|
); |
772
|
|
|
} |
773
|
|
|
if (parse_url($input, \PHP_URL_HOST) == 'localhost') { |
774
|
|
|
throw new InvalidArgumentException( |
775
|
|
|
'localhost cause problems! Please use 127.0.0.1 or another hostname' |
776
|
|
|
); |
777
|
|
|
} |
778
|
|
|
|
779
|
|
|
return $input; |
780
|
|
|
}; |
781
|
|
|
|
782
|
|
|
$baseUrl = $input->getOption('baseUrl'); |
783
|
|
|
if (null === $baseUrl) { |
784
|
|
|
if (!$input->isInteractive()) { |
785
|
|
|
throw new InvalidArgumentException('Installation base url is mandatory, use --baseUrl.'); |
786
|
|
|
} |
787
|
|
|
$baseUrl = $dialog->askAndValidate( |
788
|
|
|
$output, |
789
|
|
|
'<question>Please enter the base url:</question> ', |
790
|
|
|
$validateBaseUrl |
791
|
|
|
); |
792
|
|
|
} |
793
|
|
|
$validateBaseUrl($baseUrl); |
794
|
|
|
$baseUrl = rtrim($baseUrl, '/') . '/'; // normalize baseUrl |
795
|
|
|
|
796
|
|
|
/** |
797
|
|
|
* Correct session save (common mistake) |
798
|
|
|
*/ |
799
|
|
|
if ($sessionSave == 'file') { |
800
|
|
|
$sessionSave = 'files'; |
801
|
|
|
} |
802
|
|
|
|
803
|
|
|
/** |
804
|
|
|
* Try to create session folder |
805
|
|
|
*/ |
806
|
|
|
$defaultSessionFolder = $this->config['installationFolder'] . '/' . self::DEFAULT_SESSION_PATH; |
807
|
|
|
if ($sessionSave == 'files' && !is_dir($defaultSessionFolder)) { |
808
|
|
|
@mkdir($defaultSessionFolder); |
|
|
|
|
809
|
|
|
} |
810
|
|
|
|
811
|
|
|
$dbHost = $this->config['db_host']; |
812
|
|
|
if ($this->config['db_port'] != 3306) { |
813
|
|
|
$dbHost .= ':' . $this->config['db_port']; |
814
|
|
|
} |
815
|
|
|
|
816
|
|
|
$argv = array( |
817
|
|
|
'license_agreement_accepted' => 'yes', |
818
|
|
|
'locale' => $locale, |
819
|
|
|
'timezone' => $timezone, |
820
|
|
|
'db_host' => $dbHost, |
821
|
|
|
'db_name' => $this->config['db_name'], |
822
|
|
|
'db_user' => $this->config['db_user'], |
823
|
|
|
'db_pass' => $this->config['db_pass'], |
824
|
|
|
'db_prefix' => $this->config['db_prefix'], |
825
|
|
|
'url' => $baseUrl, |
826
|
|
|
'use_rewrites' => 'yes', |
827
|
|
|
'use_secure' => 'no', |
828
|
|
|
'secure_base_url' => '', |
829
|
|
|
'use_secure_admin' => 'no', |
830
|
|
|
'admin_username' => $adminUsername, |
831
|
|
|
'admin_lastname' => $adminLastname, |
832
|
|
|
'admin_firstname' => $adminFirstname, |
833
|
|
|
'admin_email' => $adminEmail, |
834
|
|
|
'admin_password' => $adminPassword, |
835
|
|
|
'session_save' => $sessionSave, |
836
|
|
|
'admin_frontname' => $adminFrontname, /* magento 1 */ |
837
|
|
|
'backend_frontname' => $adminFrontname, /* magento 2 */ |
838
|
|
|
'default_currency' => $currency, |
839
|
|
|
'skip_url_validation' => 'yes', |
840
|
|
|
); |
841
|
|
|
if ($useDefaultConfigParams) { |
842
|
|
|
if (strlen($defaults['encryption_key']) > 0) { |
843
|
|
|
$argv['encryption_key'] = $defaults['encryption_key']; |
844
|
|
|
} |
845
|
|
|
if (strlen($defaults['use_secure']) > 0) { |
846
|
|
|
$argv['use_secure'] = $defaults['use_secure']; |
847
|
|
|
$argv['secure_base_url'] = str_replace('http://', 'https://', $baseUrl); |
848
|
|
|
} |
849
|
|
|
if (strlen($defaults['use_rewrites']) > 0) { |
850
|
|
|
$argv['use_rewrites'] = $defaults['use_rewrites']; |
851
|
|
|
} |
852
|
|
|
} |
853
|
|
|
|
854
|
|
|
$this->runInstallScriptCommand($output, $this->config['installationFolder'], $argv); |
855
|
|
|
|
856
|
|
|
/* @var $dialog DialogHelper */ |
857
|
|
|
$dialog = $this->getHelper('dialog'); |
858
|
|
|
|
859
|
|
|
/** |
860
|
|
|
* Htaccess file |
861
|
|
|
*/ |
862
|
|
|
if ($input->getOption('useDefaultConfigParams') == null || $input->getOption('replaceHtaccessFile') != null) { |
863
|
|
|
$replaceHtaccessFile = false; |
864
|
|
|
|
865
|
|
|
if ($this->_parseBoolOption($input->getOption('replaceHtaccessFile'))) { |
866
|
|
|
$replaceHtaccessFile = true; |
867
|
|
|
} elseif ($dialog->askConfirmation( |
868
|
|
|
$output, |
869
|
|
|
'<question>Write BaseURL to .htaccess file?</question> <comment>[n]</comment>: ', |
870
|
|
|
false |
871
|
|
|
) |
872
|
|
|
) { |
873
|
|
|
$replaceHtaccessFile = true; |
874
|
|
|
} |
875
|
|
|
|
876
|
|
|
if ($replaceHtaccessFile) { |
877
|
|
|
$this->replaceHtaccessFile($baseUrl); |
878
|
|
|
} |
879
|
|
|
} |
880
|
|
|
|
881
|
|
|
\chdir($this->config['installationFolder']); |
882
|
|
|
$this->getApplication()->reinit(); |
883
|
|
|
$output->writeln('<info>Reindex all after installation</info>'); |
884
|
|
|
$this->getApplication()->run(new StringInput('index:reindex:all'), $output); |
885
|
|
|
$this->getApplication()->run(new StringInput('sys:check'), $output); |
886
|
|
|
$output->writeln('<info>Successfully installed magento</info>'); |
887
|
|
|
} |
888
|
|
|
|
889
|
|
|
/** |
890
|
|
|
* Check if we have a magento 2 or 1 installation and return path to install.php |
891
|
|
|
* |
892
|
|
|
* @return string |
893
|
|
|
*/ |
894
|
|
|
protected function getInstallScriptPath() |
895
|
|
|
{ |
896
|
|
|
$magento1InstallScriptPath = $this->config['installationFolder'] . '/' . MAGENTO_INSTALL_SCRIPT_PATH; |
897
|
|
|
$magento2InstallScriptPath = $this->config['installationFolder'] . '/dev/shell/install.php'; |
898
|
|
|
if (file_exists($magento2InstallScriptPath)) { |
899
|
|
|
return $magento2InstallScriptPath; |
900
|
|
|
} |
901
|
|
|
|
902
|
|
|
return $magento1InstallScriptPath; |
903
|
|
|
} |
904
|
|
|
|
905
|
|
|
/** |
906
|
|
|
* @param string $baseUrl |
907
|
|
|
*/ |
908
|
|
|
protected function replaceHtaccessFile($baseUrl) |
909
|
|
|
{ |
910
|
|
|
$content = file_get_contents($this->config['installationFolder'] . DIRECTORY_SEPARATOR . '.htaccess'); |
911
|
|
|
copy( |
912
|
|
|
$this->config['installationFolder'] . DIRECTORY_SEPARATOR . '.htaccess', |
913
|
|
|
$this->config['installationFolder'] . DIRECTORY_SEPARATOR . '.htaccess.dist' |
914
|
|
|
); |
915
|
|
|
$content = str_replace('#RewriteBase /magento/', 'RewriteBase ' . parse_url($baseUrl, PHP_URL_PATH), $content); |
916
|
|
|
file_put_contents($this->config['installationFolder'] . DIRECTORY_SEPARATOR . '.htaccess', $content); |
917
|
|
|
} |
918
|
|
|
|
919
|
|
|
/** |
920
|
|
|
* @param OutputInterface $output |
921
|
|
|
*/ |
922
|
|
|
protected function setDirectoryPermissions($output) |
923
|
|
|
{ |
924
|
|
|
try { |
925
|
|
|
$varFolder = $this->config['installationFolder'] . DIRECTORY_SEPARATOR . 'var'; |
926
|
|
|
if (!is_dir($varFolder)) { |
927
|
|
|
@mkdir($varFolder); |
|
|
|
|
928
|
|
|
} |
929
|
|
|
@chmod($varFolder, 0777); |
|
|
|
|
930
|
|
|
|
931
|
|
|
$varCacheFolder = $this->config['installationFolder'] . DIRECTORY_SEPARATOR . 'var/cache'; |
932
|
|
|
if (!is_dir($varCacheFolder)) { |
933
|
|
|
@mkdir($varCacheFolder); |
|
|
|
|
934
|
|
|
} |
935
|
|
|
@chmod($varCacheFolder, 0777); |
|
|
|
|
936
|
|
|
|
937
|
|
|
$mediaFolder = $this->config['installationFolder'] . DIRECTORY_SEPARATOR . 'media'; |
938
|
|
|
if (!is_dir($mediaFolder)) { |
939
|
|
|
@mkdir($mediaFolder); |
|
|
|
|
940
|
|
|
} |
941
|
|
|
@chmod($mediaFolder, 0777); |
|
|
|
|
942
|
|
|
|
943
|
|
|
$finder = Finder::create(); |
944
|
|
|
$finder->directories() |
945
|
|
|
->ignoreUnreadableDirs(true) |
946
|
|
|
->in(array($varFolder, $mediaFolder)); |
947
|
|
|
foreach ($finder as $dir) { |
948
|
|
|
@chmod($dir->getRealpath(), 0777); |
|
|
|
|
949
|
|
|
} |
950
|
|
|
} catch (Exception $e) { |
951
|
|
|
$output->writeln('<error>' . $e->getMessage() . '</error>'); |
952
|
|
|
} |
953
|
|
|
} |
954
|
|
|
|
955
|
|
|
/** |
956
|
|
|
* @return array |
957
|
|
|
*/ |
958
|
|
|
public function getCliArguments() |
|
|
|
|
959
|
|
|
{ |
960
|
|
|
if ($this->_argv === null) { |
961
|
|
|
$this->_argv = $_SERVER['argv']; |
962
|
|
|
} |
963
|
|
|
|
964
|
|
|
return $this->_argv; |
965
|
|
|
} |
966
|
|
|
|
967
|
|
|
/** |
968
|
|
|
* @param array $args |
969
|
|
|
*/ |
970
|
|
|
public function setCliArguments($args) |
971
|
|
|
{ |
972
|
|
|
$this->_argv = $args; |
973
|
|
|
} |
974
|
|
|
|
975
|
|
|
/** |
976
|
|
|
* Invoke Magento PHP install script shell/install.php |
977
|
|
|
* |
978
|
|
|
* @param OutputInterface $output |
979
|
|
|
* @param string $installationFolder folder where magento is installed in, must exists setup script in |
980
|
|
|
* @param array $argv |
981
|
|
|
* @return void |
982
|
|
|
*/ |
983
|
|
|
private function runInstallScriptCommand(OutputInterface $output, $installationFolder, array $argv) |
984
|
|
|
{ |
985
|
|
|
$installArgs = ''; |
986
|
|
|
foreach ($argv as $argName => $argValue) { |
987
|
|
|
$installArgs .= '--' . $argName . ' ' . escapeshellarg($argValue) . ' '; |
988
|
|
|
} |
989
|
|
|
|
990
|
|
|
$output->writeln('<info>Start installation process.</info>'); |
991
|
|
|
|
992
|
|
|
$installCommand = sprintf( |
993
|
|
|
'%s -ddisplay_startup_errors=1 -ddisplay_errors=1 -derror_reporting=-1 -f %s -- %s', |
994
|
|
|
OperatingSystem::getPhpBinary(), |
995
|
|
|
escapeshellarg($installationFolder . '/' . self::MAGENTO_INSTALL_SCRIPT_PATH), |
996
|
|
|
$installArgs |
997
|
|
|
); |
998
|
|
|
|
999
|
|
|
$output->writeln('<comment>' . $installCommand . '</comment>'); |
1000
|
|
|
$installException = null; |
1001
|
|
|
$installationOutput = null; |
1002
|
|
|
$returnStatus = null; |
1003
|
|
|
try { |
1004
|
|
|
Exec::run($installCommand, $installationOutput, $returnStatus); |
1005
|
|
|
} catch (Exception $installException) { |
|
|
|
|
1006
|
|
|
} |
1007
|
|
|
|
1008
|
|
|
if (isset($installException) || $returnStatus !== Exec::CODE_CLEAN_EXIT) { |
1009
|
|
|
$this->getApplication()->setAutoExit(true); |
1010
|
|
|
throw new RuntimeException( |
1011
|
|
|
sprintf('Installation failed (Exit code %s). %s', $returnStatus, $installationOutput), |
1012
|
|
|
1, |
1013
|
|
|
$installException |
1014
|
|
|
); |
1015
|
|
|
} |
1016
|
|
|
$output->writeln('<info>Successfully installed Magento</info>'); |
1017
|
|
|
$encryptionKey = trim(substr(strstr($installationOutput, ':'), 1)); |
1018
|
|
|
$output->writeln('<comment>Encryption Key:</comment> <info>' . $encryptionKey . '</info>'); |
1019
|
|
|
} |
1020
|
|
|
} |
1021
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.