Skip to content

Commit

Permalink
Merge pull request #5 from danmichaelo/master
Browse files Browse the repository at this point in the history
Various changes
  • Loading branch information
pastuhov authored Aug 27, 2016
2 parents fbf162a + cee2d60 commit 5c7a718
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 34 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,14 @@ or
}
```

By default, all arguments are escaped using
[escapeshellarg](https://secure.php.net/manual/en/function.escapeshellarg.php).
If you need to pass unescaped arguments, use `{!name!}`, like so:

```php
Command::exec('echo {!path!}', ['path' => '$PATH']);
```

## Testing

``` bash
Expand Down
57 changes: 25 additions & 32 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,27 @@ private function __construct()
/**
* Execute command with params.
*
* @param string $commandLine
* @param string $command
* @param array $params
*
* @return bool|string
*
* @throws \Exception
*/
public static function exec($commandLine, array $params = array())
public static function exec($command, array $params = array(), $mergeStdErr=true)
{
if (empty($commandLine)) {
throw new \Exception('Command line is empty');
if (empty($command)) {
throw new \InvalidArgumentException('Command line is empty');
}

$commandLine = self::bindParams($commandLine, $params);
$command = self::bindParams($command, $params);

exec($commandLine, $output, $code);
if ($mergeStdErr) {
// Redirect stderr to stdout to include it in $output
$command .= ' 2>&1';
}

exec($command, $output, $code);

if (count($output) === 0) {
$output = $code;
Expand All @@ -37,7 +42,7 @@ public static function exec($commandLine, array $params = array())
}

if ($code !== 0) {
throw new \Exception($output . ' Command line: ' . $commandLine);
throw new CommandException($command, $output, $code);
}

return $output;
Expand All @@ -46,38 +51,26 @@ public static function exec($commandLine, array $params = array())
/**
* Bind params to command.
*
* @param string $commandLine
* @param string $command
* @param array $params
*
* @return string
*/
public static function bindParams($commandLine, array $params)
public static function bindParams($command, array $params)
{
if (count($params) > 0) {
$wrapper = function ($string) {
return '{' . $string . '}';
};
$converter = function ($var) {
if (is_array($var)) {
$var = implode(' ', $var);
}

return $var;
};
$wrappers = array();
$converters = array();
foreach ($params as $key => $value) {

// Escaped
$wrappers[] = '{' . $key . '}';
$converters[] = escapeshellarg(is_array($value) ? implode(' ', $value) : $value);

$commandLine = str_replace(
array_map(
$wrapper,
array_keys($params)
),
array_map(
$converter,
array_values($params)
),
$commandLine
);
// Unescaped
$wrappers[] = '{!' . $key . '!}';
$converters[] = is_array($value) ? implode(' ', $value) : $value;
}

return $commandLine;
return str_replace($wrappers, $converters, $command);
}
}
39 changes: 39 additions & 0 deletions src/CommandException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
namespace pastuhov\Command;

class CommandException extends \RuntimeException
{
protected $command;
protected $output;
protected $returnCode;

public function __construct($command, $output, $returnCode)
{
$this->command = $command;
$this->output = $output;
$this->returnCode = $returnCode;

if ($this->returnCode == 127) {
$message = 'Command not found: "' . $this->getCommand() . '"';
} else {
$message = 'Command "' . $this->getCommand() . '" exited with code ' . $this->getReturnCode() . ': ' . $this->getOutput();
}

parent::__construct($message);
}

public function getCommand()
{
return $this->command;
}

public function getOutput()
{
return $this->output;
}

public function getReturnCode()
{
return $this->returnCode;
}
}
34 changes: 32 additions & 2 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function testExec()
*/
public function testExecException()
{
$this->setExpectedException('Exception');
$this->setExpectedException('pastuhov\Command\CommandException');

$output = Command::exec(
'echo111'
Expand All @@ -43,10 +43,40 @@ public function testExecException()
*/
public function testExecEmptyCommand()
{
$this->setExpectedException('Exception');
$this->setExpectedException('InvalidArgumentException');

$output = Command::exec(
''
);
}

/**
* Test that arguments are escaped by default
*/
public function testArgumentsEscapedByDefault()
{
$output = Command::exec(
'echo {phrase}',
[
'phrase' => 'hello $PATH',
]
);

$this->assertEquals('hello $PATH', $output);
}

/**
* Test that unescaped arguments can be passed
*/
public function testUnescapedArguments()
{
$output = Command::exec(
'echo {!phrase!}',
[
'phrase' => 'hello $PATH',
]
);

$this->assertRegexp('/\//', $output);
}
}

0 comments on commit 5c7a718

Please sign in to comment.