Skip to content

Commit

Permalink
Refactor preflight verification tests into a PreflightVerify class.
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-1-anderson committed Jul 28, 2017
1 parent e2c8a49 commit fa61eb5
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 16 deletions.
12 changes: 12 additions & 0 deletions src/Config/Environment.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,16 @@ public static function isWindows($os = null)
{
return strtoupper(substr($os ?: PHP_OS, 0, 3)) === 'WIN';
}

/**
* Verify that we are running PHP through the command line interface.
*
* @return
* A boolean value that is true when PHP is being run through the command line,
* and false if being run through cgi or mod_php.
*/
function verifyCLI() {
return (php_sapi_name() == 'cli' || (is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0));
}

}
34 changes: 18 additions & 16 deletions src/Preflight/Preflight.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,21 @@ class Preflight
*/
protected $environment;

public function __construct(Environment $environment)
/**
* @var PreflightVerify
*/
protected $verify;

/**
* @var ConfigLocator
*/
protected $configLocator;

public function __construct(Environment $environment, $verify = null, $configLocator = null)
{
$this->environment = $environment;
$this->verify = $verify ?: new PreflightVerify();
$this->configLocator = $configLocator ?: new ConfigLocator();
}

public function init($preflightArgs)
Expand Down Expand Up @@ -102,14 +114,14 @@ public function run($argv)

protected function doRun($argv)
{
// Fail fast if the PHP version is not at least 5.6.0.
$this->confirmPhpVersion('5.6.0');
// Fail fast if there is anything in our environment that does not check out
$this->verify->verify($this->environment);

// Get the preflight args and begin collecting configuration files.
$preflightArgs = $this->preflightArgs($argv);
$configLocator = $this->prepareConfig($preflightArgs, $this->environment);

// Do legacy initialization
// Do legacy initialization (load static includes, define old constants, etc.)
$this->init($preflightArgs);

// Determine the local site targeted, if any.
Expand All @@ -130,8 +142,8 @@ protected function doRun($argv)
$container = DependencyInjection::initContainer($application, $config, $input, $output);

// We need to check the php minimum version again, in case anyone
// has set it to something higher.
$this->confirmPhpVersion($config->get('drush.php.minimum-version'));
// has set it to something higher in one of the config files we loaded.
$this->verify->confirmPhpVersion($config->get('drush.php.minimum-version'));

// Find all of the available commandfiles, save for those that are
// provided by modules in the selected site; those will be added
Expand Down Expand Up @@ -228,16 +240,6 @@ protected function findCommandFileSearchPath($preflightArgs)
return $searchpath;
}

/**
* Fail fast if the php version does not meet the minimum requirements.
*/
protected function confirmPhpVersion($minimumPhpVersion)
{
if (version_compare(phpversion(), $minimumPhpVersion) < 0 && !getenv('DRUSH_NO_MIN_PHP')) {
throw new \Exception(dt('Your command line PHP installation is too old. Drush requires at least PHP !version. To suppress this check, set the environment variable DRUSH_NO_MIN_PHP=1', ['!version' => $minimumPhpVersion]));
}
}

/**
* Make sure we are notified on exit, and when bad things happen.
*/
Expand Down
114 changes: 114 additions & 0 deletions src/Preflight/PreflightVerify.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php
namespace Drush\Preflight;

use Drush\Drush;
use Drush\Config\Environment;
use Drush\Utils\StringUtils;

class PreflightVerify
{
/**
* Throw an exception if the environment is not right for running Drush.
*
* @param Environment $environment
*/
public function verify(Environment $environment)
{
// Fail fast if the PHP version is not at least 5.6.0.
// We'll come back and check this again later, in case someone
// set a higher value in a configuration file.
$this->confirmPhpVersion('5.6.0');

// Fail if this is not a CLI php
$this->confirmUsingCLI($environment);

// Fail if any manditory functions have been disabled, or any
// illegal options have been set in php.ini.
$this->checkPhpIni();
}

/**
* Fail fast if the php version does not meet the minimum requirements.
*
* @param string $minimumPhpVersion
* The minimum allowable php version
*/
public function confirmPhpVersion($minimumPhpVersion)
{
if (version_compare(phpversion(), $minimumPhpVersion) < 0 && !getenv('DRUSH_NO_MIN_PHP')) {
throw new \Exception(StringUtils::interpolate('Your command line PHP installation is too old. Drush requires at least PHP {version}. To suppress this check, set the environment variable DRUSH_NO_MIN_PHP=1', ['version' => $minimumPhpVersion]));
}
}

/**
* Fail if not being run from the command line.
*
* @param Environment $environment
*/
protected function confirmUsingCLI(Environment $environment)
{
if (!$environment->verifyCLI()) {
throw new \Exception(StringUtils::interpolate('Drush is designed to run via the command line.'));
}
}

/**
* Evaluate the environment before command bootstrapping
* begins. If the php environment is too restrictive, then
* notify the user that a setting change is needed and abort.
*/
protected function checkPhpIni()
{
$ini_checks = ['safe_mode' => '', 'open_basedir' => '', 'disable_functions' => ['exec', 'system'], 'disable_classes' => ''];

// Test to insure that certain php ini restrictions have not been enabled
$prohibited_list = [];
foreach ($ini_checks as $prohibited_mode => $disallowed_value) {
$ini_value = ini_get($prohibited_mode);
if ($this->invalidIniValue($ini_value, $disallowed_value)) {
$prohibited_list[] = $prohibited_mode;
}
}
if (!empty($prohibited_list)) {
throw new \Exception(StringUtils::interpolate('The following restricted PHP modes have non-empty values: {prohibited_list}. This configuration is incompatible with drush. {php_ini_msg}', ['prohibited_list' => implode(' and ', $prohibited_list), 'php_ini_msg' => $this->loadedPhpIniMessage()]));
}
}

/**
* Determine whether an ini value is valid based on the criteria.
*
* @param string $ini_value
* The value of the ini setting being tested.
* @param string|string[] $disallowed_value
* The value that the ini seting cannot be, or a list of disallowed
* values that cannot appear in the setting.
* @return bool
*/
protected function invalidIniValue($ini_value, $disallowed_value)
{
if (empty($disallowed_value)) {
return !empty($ini_value) && (strcasecmp($ini_value, 'off') != 0);
} else {
foreach ($disallowed_value as $test_value) {
if (preg_match('/(^|,)' . $test_value . '(,|$)/', $ini_value)) {
return true;
}
}
}
return false;
}

/**
* Returns a localizable message about php.ini that
* varies depending on whether the php_ini_loaded_file()
* is available or not.
*/
protected function loadedPhpIniMessage()
{
if (function_exists('php_ini_loaded_file')) {
return StringUtils::interpolate('Please check your configuration settings in !phpini or in your drush.ini file; see examples/example.drush.ini for details.', ['!phpini' => php_ini_loaded_file()]);
} else {
return StringUtils::interpolate('Please check your configuration settings in your php.ini file or in your drush.ini file; see examples/example.drush.ini for details.');
}
}
}

0 comments on commit fa61eb5

Please sign in to comment.