Skip to content

Commit

Permalink
Forward port Magento installer invocation, fixes #267
Browse files Browse the repository at this point in the history
It came to the attention in #267 that some of the improvements in Magerun 1
when installing Magento were not yet forward ported to Magerun 2.

Fixes in detail:

- Use the same php binary as Magerun is running with (solves the issue
  with aliasing the php binary as reported in #267)

- Using Exec::run() utility (solves the issue of not showing the error
  output if the install command fails as reported in #267)

- When invoking the command, PHP is executed with full error reporting so
  that errors during the install can be more easily trouble-shooted

Refs:

- #267

- Command: install
  • Loading branch information
ktomk committed Feb 11, 2017
1 parent f7c5e77 commit db5e96b
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 47 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -3,6 +3,7 @@ RECENT CHANGES

1.3.1
-----
* Fix: Install command using wrong php binary and eating installer errors (report by David Lambauer, fix by Tom Klingenberg, #267)
* Fix: Minor PHP version for Magento 2 extensions (by Alexander Turiak, #269)
* Fix: Magento object manager usage in production mode (by Tom Klingenberg, #241)
* Fix: Support for db-setting arrays (e.g. driver_options) (by Tom Klingenberg)
Expand Down
91 changes: 53 additions & 38 deletions src/N98/Magento/Command/Installer/SubCommand/InstallMagento.php
Expand Up @@ -4,15 +4,21 @@

use Exception;
use N98\Magento\Command\SubCommand\AbstractSubCommand;
use N98\Util\Exec;
use N98\Util\OperatingSystem;
use RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;

class InstallMagento extends AbstractSubCommand
{
/**
* @var int
* @deprecated since since 1.3.1; Use constant from Exec-Utility instead
* @see Exec::CODE_CLEAN_EXIT
*/
const EXEC_STATUS_OK = 0;

const MAGENTO_INSTALL_SCRIPT_PATH = 'bin/magento';

/**
* @var \Closure
*/
Expand Down Expand Up @@ -196,35 +202,19 @@ public function execute()

$this->config->setArray('installation_args', $argv);

$installArgs = '';
foreach ($argv as $argName => $argValue) {
if (is_null($argValue)) {
$installArgs .= '--' . $argName . ' ';
} elseif (is_bool($argValue)) {
if ($argValue) {
$argValue = '1';
} else {
$argValue = '0';
}
$installArgs .= '--' . $argName . '=' . $argValue . ' ';
} else {
$installArgs .= '--' . $argName . '=' . escapeshellarg($argValue) . ' ';
}
}

$this->output->writeln('<info>Start installation process.</info>');
$this->_runInstaller($installArgs);
$this->runInstallScriptCommand($this->output, $this->config->getString('installationFolder'), $argv);
}

/**
* @deprecated since 1.3.1 (obsolete)
* @return string
* @throws Exception
*/
protected function getInstallScriptPath()
{
$installerScript = $this->config->getString('installationFolder') . '/bin/magento';
$installerScript = $this->config->getString('installationFolder') . '/' . self::MAGENTO_INSTALL_SCRIPT_PATH;
if (!file_exists($installerScript)) {
throw new \RuntimeException('Installation script was not found.', 1);
throw new RuntimeException('Installation script was not found.', 1);
}

return $installerScript;
Expand Down Expand Up @@ -261,30 +251,55 @@ protected function _prepareDbHost()
}

/**
* @param string $installArgs
* Invoke Magento PHP install script bin/magento setup:install
*
* @throws Exception
* @param OutputInterface $output
* @param string $installationFolder folder where magento is installed in, must exists setup script in
* @param array $argv
* @return void
*/
protected function _runInstaller($installArgs)
private function runInstallScriptCommand(OutputInterface $output, $installationFolder, array $argv)
{
$installArgs = '';
foreach ($argv as $argName => $argValue) {
if (is_null($argValue)) {
$installArgs .= '--' . $argName . ' ';
} elseif (is_bool($argValue)) {
$installArgs .= '--' . $argName . '=' . (int) $argValue . ' ';
} else {
$installArgs .= '--' . $argName . '=' . escapeshellarg($argValue) . ' ';
}
}

$output->writeln('<info>Start installation process.</info>');

$installCommand = sprintf(
'%s -ddisplay_startup_errors=1 -ddisplay_errors=1 -derror_reporting=-1 -f %s -- setup:install %s',
OperatingSystem::getPhpBinary(),
escapeshellarg($installationFolder . '/' . self::MAGENTO_INSTALL_SCRIPT_PATH),
$installArgs
);

$output->writeln('<comment>' . $installCommand . '</comment>');
$installException = null;
$installationOutput = null;
$returnStatus = null;

if (OperatingSystem::isWindows()) {
$installCommand = 'php ' . $this->getInstallScriptPath() . ' setup:install ' . $installArgs;
} else {
$installCommand = '/usr/bin/env php ' . $this->getInstallScriptPath() . ' setup:install ' . $installArgs;
try {
Exec::run($installCommand, $installationOutput, $returnStatus);
} catch (Exception $installException) {
/* fall-through intended */
}

$this->output->writeln('<comment>' . $installCommand . '</comment>');
exec($installCommand, $installationOutput, $returnStatus);
$installationOutput = implode(PHP_EOL, $installationOutput);
if ($returnStatus !== self::EXEC_STATUS_OK) {
throw new \RuntimeException('Installation failed.' . $installationOutput, 1);
} else {
$this->output->writeln('<info>Successfully installed Magento</info>');
$encryptionKey = trim(substr($installationOutput, strpos($installationOutput, ':') + 1));
$this->output->writeln('<comment>Encryption Key:</comment> <info>' . $encryptionKey . '</info>');
if (isset($installException) || $returnStatus !== Exec::CODE_CLEAN_EXIT) {
$this->getCommand()->getApplication()->setAutoExit(true);
throw new RuntimeException(
sprintf('Installation failed (Exit code %s). %s', $returnStatus, $installationOutput),
1,
$installException
);
}
$output->writeln('<info>Successfully installed Magento</info>');
$encryptionKey = trim(substr(strstr($installationOutput, ':'), 1));
$output->writeln('<comment>Encryption Key:</comment> <info>' . $encryptionKey . '</info>');
}
}
26 changes: 18 additions & 8 deletions src/N98/Util/Exec.php
Expand Up @@ -6,6 +6,7 @@

/**
* Class Exec
*
* @package N98\Util
*/
class Exec
Expand All @@ -22,18 +23,25 @@ class Exec

/**
* @param string $command
* @param string $commandOutput
* @param string|null $output
* @param int $returnCode
*/
public static function run($command, &$commandOutput = null, &$returnCode = null)
public static function run($command, &$output = null, &$returnCode = null)
{
if (!self::allowed()) {
$message = sprintf("No PHP exec(), can not execute command '%s'.", $command);
throw new RuntimeException($message);
}

$command = $command . self::REDIRECT_STDERR_TO_STDOUT;

exec($command, $commandOutput, $returnCode);
$commandOutput = self::parseCommandOutput($commandOutput);
exec($command, $outputArray, $returnCode);
$output = self::parseCommandOutput((array) $outputArray);

if ($returnCode !== self::CODE_CLEAN_EXIT) {
throw new RuntimeException($commandOutput);
throw new RuntimeException(
sprintf("Exit status %d for command %s. Output was: %s", $returnCode, $command, $output)
);
}
}

Expand All @@ -48,11 +56,13 @@ public static function allowed()
}

/**
* @param $commandOutput
* string from array of strings representing one line per entry
*
* @param array $commandOutput
* @return string
*/
private static function parseCommandOutput($commandOutput)
private static function parseCommandOutput(array $commandOutput)
{
return implode(PHP_EOL, $commandOutput);
return implode(PHP_EOL, $commandOutput) . PHP_EOL;
}
}
23 changes: 22 additions & 1 deletion src/N98/Util/OperatingSystem.php
Expand Up @@ -81,7 +81,9 @@ public static function isProgramInstalled($program)
}

/**
* @return string
* Home directory of the current user
*
* @return string|false false in case there is no environment variable related to the home directory
*/
public static function getHomeDir()
{
Expand Down Expand Up @@ -113,4 +115,23 @@ public static function getCwd()
{
return getcwd();
}

/**
* Retrieve path to php binary
*
* @return string
*/
public static function getPhpBinary()
{
// PHP_BINARY (>= php 5.4)
if (defined('PHP_BINARY')) {
return PHP_BINARY;
}

if (self::isWindows()) {
return 'php';
}

return '/usr/bin/env php';
}
}

0 comments on commit db5e96b

Please sign in to comment.