Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
25.00% |
1 / 4 |
CRAP | |
58.46% |
38 / 65 |
ExecutableCheck | |
0.00% |
0 / 1 |
|
25.00% |
1 / 4 |
19.67 | |
58.46% |
38 / 65 |
getDefaultGroupName() | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
getDefaultSettingGroupName() | |
0.00% |
0 / 1 |
2.15 | |
66.67% |
2 / 3 |
|||
run() | |
0.00% |
0 / 1 |
3.06 | |
81.40% |
35 / 43 |
|||
validExecutable($value) | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 18 |
<?php | |
namespace Environaut\Checks; | |
use Environaut\Checks\Check; | |
/** | |
* Check to get absolute paths to executable files that | |
* may be used within an application. As even paths to | |
* simple tools like "ls", "find" or "grep" may not be | |
* accessible in e.g. crontabs due to non-configured | |
* default PATH environment variables they can be searched | |
* and configured prior running the application (and thus | |
* always use the validated absolute executable paths). | |
* | |
* Supported parameters are: | |
* - "command": name of executable/command to check | |
* - "setting": name of setting to use for absolute path storage (for export) | |
* - "setting_group": name of settings group to use (for export; defaults to "config") | |
* - "question": question to ask the user (defaults to "Path to the executable [command]") | |
* - "default": default command or executable path to try (defaults to "/usr/bin/[command]") | |
* - "validator": validator callable to use (defaults to one, that uses "which" to find the path of the command) | |
* - "max_attempts": maximum number of attempts a user is allowed to have for correct input of a path | |
*/ | |
class ExecutableCheck extends Check | |
{ | |
/** | |
* Default group of settings that this check stores in the result. | |
*/ | |
const DEFAULT_SETTING_GROUP_NAME = 'config'; | |
/** | |
* Default group name used in messages of the report. | |
* By default also used as default setting group name if not customized. | |
*/ | |
const DEFAULT_CUSTOM_GROUP_NAME = 'Executables'; | |
/** | |
* Returns the default group name this check uses when none is specified. | |
* | |
* @return string default group name of the check | |
*/ | |
public function getDefaultGroupName() | |
{ | |
return self::DEFAULT_CUSTOM_GROUP_NAME; | |
} | |
/** | |
* Returns the default group name this check uses for settings when none is specified. | |
* | |
* @return string default group name of settings of this check | |
*/ | |
public function getDefaultSettingGroupName() | |
{ | |
if ($this->group !== self::DEFAULT_CUSTOM_GROUP_NAME) { | |
return $this->group; | |
} | |
return self::DEFAULT_SETTING_GROUP_NAME; | |
} | |
/** | |
* Ask user for an absolute path to the given executable or try to determine it | |
* by itself using the default value (on confirmation). | |
* | |
* @return boolean true | |
* | |
* @throws \InvalidArgumentException on setup errors like "choices" can't be interpreted or parameters being wrong | |
* @throws \RuntimeException if there is no data to read in the input stream | |
* @throws \Exception when the maximum number of attempts has been reached and no valid response has been given | |
*/ | |
public function run() | |
{ | |
$output = $this->getOutputStream(); | |
$dialog = $this->getDialogHelper(); | |
$command = $this->parameters->get('command', $this->getName()); | |
$setting = $this->parameters->get('setting', 'cmd.' . $command); | |
$setting_group = $this->parameters->get('setting_group'); | |
$default = $this->parameters->get('default', '/usr/bin/' . $command); | |
$choices = $this->parameters->get( | |
'choices', | |
array( | |
'/bin/', | |
'/usr/bin/', | |
'/usr/sbin/', | |
'/usr/local/bin/', | |
'/usr/local/sbin/', | |
) | |
); | |
$validator = $this->parameters->get('validator', array($this, 'validExecutable')); | |
$max_attempts = $this->parameters->get('max_attempts', false); | |
if ($this->cache->has($setting, $setting_group)) { | |
$cached_setting = $this->cache->get($setting, $setting_group); | |
$this->addInfo( | |
"Setting [" . $cached_setting->getGroup() . "][$setting] already configured. Using " . | |
'value: ' . var_export($cached_setting->getValue(), true) | |
); | |
$this->result->addSetting($cached_setting); | |
return true; | |
} | |
$question = '<question>' . $this->parameters->get( | |
'question', | |
'Path to the executable "' . $command . '"' | |
); | |
// add default value to question if specified | |
if (null !== $default) { | |
$question .= "</question> (Default: which $default)"; | |
} else { | |
$question .= '</question>'; | |
} | |
$question .= ': '; | |
// ask for path to executable with validation and autocomplete of common executable directories like /usr/bin | |
$absolute_executable_path = $dialog->askAndValidate( | |
$output, | |
$question, | |
$validator, | |
$max_attempts, | |
$default, | |
$choices | |
); | |
$this->addCachableSetting($setting, $absolute_executable_path, $setting_group); | |
$this->addInfo('Got path to executable "' . $command . '": ' . $absolute_executable_path); | |
return true; | |
} | |
/** | |
* Checks whether the given input value leads to an executable that | |
* matches the configured version_mask parameter. | |
* | |
* @param string $value path to an executable | |
* | |
* @return string absolute path to executable | |
* | |
* @throws \InvalidArgumentException in case of non-existing executable at the given path or version mismatch | |
*/ | |
public function validExecutable($value) | |
{ | |
$val = trim($value); | |
if (empty($val)) { | |
throw new \InvalidArgumentException( | |
'Not a valid executable path. Please specify a command (like "ls") or a path (like "/usr/bin/ls").' | |
); | |
} | |
$executable = trim(shell_exec('which ' . $val)); | |
if (!$executable) { | |
throw new \InvalidArgumentException('Could not find executable: ' . $val); | |
} | |
$command = $this->parameters->get('command', $this->getName()); | |
$cli_option = $this->parameters->get('version_parameter', '--version'); | |
$version_mask = $this->parameters->get('version_mask', '/Version/'); | |
if ($version_mask) { | |
$version_info_raw = trim(shell_exec('cat /dev/null | ' . $executable . ' ' . $cli_option . ' 2>&1')); | |
if (!preg_match($version_mask, $version_info_raw, $matches, PREG_OFFSET_CAPTURE)) { | |
throw new \InvalidArgumentException( | |
'Could not get version information for "' . $command . '" using "' . $executable . '".' | |
); | |
} | |
} | |
return $executable; | |
} | |
} |