mirror of
https://github.com/n3w/helpers-functions-cli.git
synced 2025-12-19 12:43:22 +00:00
feat: Add which() method and refactor run_command()
This commit is contained in:
parent
630efc99d6
commit
33090aee1f
1 changed files with 105 additions and 55 deletions
160
src/Cli/Cli.php
160
src/Cli/Cli.php
|
|
@ -2,14 +2,115 @@
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the "PHP Helpers: Command-line Functions" repository.
|
||||||
|
*
|
||||||
|
* Copyright 2019-2021 Alannah Kearney <hi@alannahkearney.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENCE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
namespace pointybeard\Helpers\Functions\Cli;
|
namespace pointybeard\Helpers\Functions\Cli;
|
||||||
|
|
||||||
use pointybeard\Helpers\Cli\Input;
|
|
||||||
use pointybeard\Helpers\Cli\Colour;
|
use pointybeard\Helpers\Cli\Colour;
|
||||||
use pointybeard\Helpers\Functions\Flags;
|
use pointybeard\Helpers\Cli\Input;
|
||||||
use pointybeard\Helpers\Functions\Strings;
|
|
||||||
use pointybeard\Helpers\Functions\Arrays;
|
use pointybeard\Helpers\Functions\Arrays;
|
||||||
use pointybeard\Helpers\Functions\Debug;
|
use pointybeard\Helpers\Functions\Debug;
|
||||||
|
use pointybeard\Helpers\Functions\Flags;
|
||||||
|
use pointybeard\Helpers\Functions\Strings;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Uses proc_open() to run a command on the shell. Output and errors are captured
|
||||||
|
* and returned. If the command "fails" to run (i.e. return code is != 0), this
|
||||||
|
* function will throw an exception.
|
||||||
|
*
|
||||||
|
* Note that some commands will return a non-zero status code to signify, for
|
||||||
|
* example, no results found. This function is unable to tell the difference and
|
||||||
|
* will trigger an exception regardless. In this instance, It is advised to trap
|
||||||
|
* that exception and inspect both $stderr and $stdout to decide if it was
|
||||||
|
* actually due to failed command execution.
|
||||||
|
*
|
||||||
|
* @param string $command the full bash command to run
|
||||||
|
* @param string $stdout (optional) reference to capture output from STDOUT
|
||||||
|
* @param string $stderr (optional) reference to capture output from STDERR
|
||||||
|
* #param string $exitCode (options) reference to capture the command exit code
|
||||||
|
*
|
||||||
|
* @throws RunCommandFailedException
|
||||||
|
*/
|
||||||
|
if (!function_exists(__NAMESPACE__.'\run_command')) {
|
||||||
|
function run_command(string $command, string &$stdout = null, string &$stderr = null, int &$exitCode = null): void
|
||||||
|
{
|
||||||
|
$pipes = null;
|
||||||
|
$exitCode = null;
|
||||||
|
|
||||||
|
$proc = proc_open(
|
||||||
|
"{$command};echo $? >&3",
|
||||||
|
[
|
||||||
|
0 => ['pipe', 'r'], // STDIN
|
||||||
|
1 => ['pipe', 'w'], // STDOUT
|
||||||
|
2 => ['pipe', 'w'], // STDERR
|
||||||
|
3 => ['pipe', 'w'], // Used to capture the exit code
|
||||||
|
],
|
||||||
|
$pipes,
|
||||||
|
getcwd(),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
// Close STDIN stream
|
||||||
|
fclose($pipes[0]);
|
||||||
|
|
||||||
|
// (guard) proc_open failed to return a resource
|
||||||
|
if (false == is_resource($proc)) {
|
||||||
|
throw new Exceptions\RunCommandFailedException($command, 'proc_open() returned FALSE.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get contents of STDOUT and close stream
|
||||||
|
$stdout = trim(stream_get_contents($pipes[1]));
|
||||||
|
fclose($pipes[1]);
|
||||||
|
|
||||||
|
// Get contents od STDERR and close stream
|
||||||
|
$stderr = trim(stream_get_contents($pipes[2]));
|
||||||
|
fclose($pipes[2]);
|
||||||
|
|
||||||
|
// Grab the exit code then close the stream
|
||||||
|
if (false == feof($pipes[3])) {
|
||||||
|
$exitCode = (int) trim(stream_get_contents($pipes[3]));
|
||||||
|
}
|
||||||
|
fclose($pipes[3]);
|
||||||
|
|
||||||
|
// Close the process we created
|
||||||
|
proc_close($proc);
|
||||||
|
|
||||||
|
// (guard) proc_close return indiciated a failure
|
||||||
|
if (0 != $exitCode) {
|
||||||
|
// There was some kind of error. Throw an exception.
|
||||||
|
// If STDERR is empty, in effort to give back something
|
||||||
|
// meaningful, grab contents of STDOUT instead
|
||||||
|
throw new Exceptions\RunCommandFailedException($command, true == empty(trim($stderr)) ? $stdout : $stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the pathname for a specified command (or null if it cannot be found)
|
||||||
|
*
|
||||||
|
* @params $command the name of the command to look for
|
||||||
|
*
|
||||||
|
* @returns string|null
|
||||||
|
*/
|
||||||
|
if (!function_exists(__NAMESPACE__.'\which')) {
|
||||||
|
function which(string $command): ?string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
run_command("which {$command}", $output);
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$output = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if bash can be invoked.
|
* Checks if bash can be invoked.
|
||||||
|
|
@ -144,7 +245,7 @@ if (!function_exists(__NAMESPACE__."\display_error_and_exit")) {
|
||||||
$edgePadding = str_repeat($padCharacter, $edgePaddingLength);
|
$edgePadding = str_repeat($padCharacter, $edgePaddingLength);
|
||||||
|
|
||||||
// Convenience function for adding the background to a line.
|
// Convenience function for adding the background to a line.
|
||||||
$add_background = function (string $string, bool $bold = false) use ($padCharacter, $edgePadding, $background): string {
|
$add_background = function (string $string, bool $bold = false) use ($edgePadding, $background): string {
|
||||||
$string = $edgePadding.$string.$edgePadding;
|
$string = $edgePadding.$string.$edgePadding;
|
||||||
|
|
||||||
return Colour\Colour::colourise(
|
return Colour\Colour::colourise(
|
||||||
|
|
@ -210,54 +311,3 @@ if (!function_exists(__NAMESPACE__."\display_error_and_exit")) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Uses proc_open() to run a command on the shell. Output and errors are captured
|
|
||||||
* and returned. If the command "fails" to run (i.e. return code is != 0), this
|
|
||||||
* function will throw an exception.
|
|
||||||
*
|
|
||||||
* Note that some commands will return a non-zero status code to signify, for
|
|
||||||
* example, no results found. This function is unable to tell the difference and
|
|
||||||
* will trigger an exception regardless. In this instance, It is advised to trap
|
|
||||||
* that exception and inspect both $stderr and $stdout to decide if it was
|
|
||||||
* actually due to failed command execution.
|
|
||||||
*
|
|
||||||
* @param string $command the full bash command to run
|
|
||||||
* @param string $stdout (optional) reference to capture output from STDOUT
|
|
||||||
* @param string $stderr (optional) reference to capture output from STDERR
|
|
||||||
*
|
|
||||||
* @throws RunCommandFailedException
|
|
||||||
*/
|
|
||||||
if (!function_exists(__NAMESPACE__.'\run_command')) {
|
|
||||||
function run_command(string $command, string &$stdout = null, string &$stderr = null): void
|
|
||||||
{
|
|
||||||
$pipes = null;
|
|
||||||
$return = null;
|
|
||||||
|
|
||||||
$proc = proc_open(
|
|
||||||
$command,
|
|
||||||
[
|
|
||||||
['pipe', 'r'], // STDIN
|
|
||||||
['pipe', 'w'], // STDOUT
|
|
||||||
['pipe', 'w'], // STDERR
|
|
||||||
],
|
|
||||||
$pipes,
|
|
||||||
getcwd(),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
if (true == is_resource($proc)) {
|
|
||||||
$stdout = trim(stream_get_contents($pipes[1]));
|
|
||||||
$stderr = trim(stream_get_contents($pipes[2]));
|
|
||||||
|
|
||||||
// Check the return code. If it's not 0, then the command failed.
|
|
||||||
if (0 != proc_close($proc)) {
|
|
||||||
throw new Exceptions\RunCommandFailedException($command, (string) $stderr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Something went horribly wrong with proc_open(). This should
|
|
||||||
// nearly never happen, but, accounting for it regardless.
|
|
||||||
throw new Exceptions\RunCommandFailedException($command, 'proc_open() returned FALSE');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue