<?php
declare(strict_types=1);
namespace Airship\Barge;
use ParagonIE\Halite\Asymmetric\SignaturePublicKey;
/**
* Class Command
*
* This is the base class for all barge commands.
*
* @package Airship\Barge
*/
abstract class Command
{
const TAB_SIZE = 8;
public $essential = false;
public $display = 65535;
public $name = 'CommandName';
public $description = 'CLI description';
public $tag = [
'color' => '',
'text' => ''
];
public static $cache = []; // Cache references to other commands
public static $userConfig; // Current user's configuration
protected $config = []; // config.json
// Database adapter
protected $db;
// BASH COLORS
protected $c = [
'' => "\033[0;39m",
'red' => "\033[0;31m",
'green' => "\033[0;32m",
'blue' => "\033[1;34m",
'cyan' => "\033[1;36m",
'silver' => "\033[0;37m",
'yellow' => "\033[0;93m"
];
/**
* Execute a command
*/
abstract public function fire(array $args = []);
/**
* Return a command
*
* @param string $name
* @param boolean $cache
* @return Command
*/
public function getCommandObject($name, $cache = true): Command
{
return self::getCommandStatic($name, $cache);
}
/**
* Return a command (statically callable)
*
* @param string $name
* @param boolean $cache
* @return Command
*/
public static function getCommandStatic($name, $cache = true): Command
{
$_name = '\\Airship\\Barge\\Commands\\'.\ucfirst($name);
if (!empty(self::$cache[$name])) {
return self::$cache[$name];
}
if ($cache) {
self::$cache[$name] = new $_name;
return self::$cache[$name];
}
return new $_name;
}
/**
* Grab the git commit hash
*
* @param string $projectRoot
* @return string
* @throws \Exception
*/
public function getGitCommitHash(string $projectRoot): string
{
if (!\is_dir($projectRoot . '/.git')) {
return '';
}
$command = "/usr/bin/env bash -c 'echo OK'";
if (\rtrim(\shell_exec($command)) !== 'OK') {
throw new \Exception("Can't invoke bash");
}
$dir = \getcwd();
\chdir($projectRoot);
$hash = \rtrim(\shell_exec("git rev-parse HEAD"));
\chdir($dir);
return $hash;
}
/**
* Return the size of hte current terminal window
*
* @return array (int, int)
*/
public function getScreenSize()
{
$output = [];
\preg_match_all(
"/rows.([0-9]+);.columns.([0-9]+);/",
\strtolower(\exec('stty -a |grep columns')),
$output
);
if (\sizeof($output) === 3) {
return [
'width' => $output[2][0],
'height' => $output[1][0]
];
}
return [0, 0];
}
/**
* Get a token for HTTP requests
*
* @param string $supplier
* @return string|null
*/
public function getToken($supplier)
{
if (!isset($this->config['suppliers'][$supplier])) {
return null;
}
if (empty($this->config['suppliers'][$supplier]['token'])) {
return null;
}
$v = $this->config['suppliers'][$supplier]['token'];
return $v['selector'].':'.$v['validator'];
}
/**
* @param $data
*/
final public function storeConfig(array $data = [])
{
$this->config = $data;
}
/**
* @return bool
*/
final public function saveConfig(): bool
{
return \file_put_contents(
AIRSHIP_LOCAL_CONFIG."/config.json",
\json_encode($this->config, JSON_PRETTY_PRINT)
) !== false;
}
/**
* Prompt the user for an input value
*
* @param string $text
* @return string
*/
final protected function prompt(string $text = ''): string
{
static $fp = null;
if ($fp === null) {
$fp = \fopen('php://stdin', 'r');
}
echo $text;
return \substr(\fgets($fp), 0, -1);
}
/**
* Interactively prompts for input without echoing to the terminal.
* Requires a bash shell or Windows and won't work with
* safe_mode settings (Uses `shell_exec`)
*
* @ref http://www.sitepoint.com/interactive-cli-password-prompt-in-php/
*/
final protected function silentPrompt($text = "Enter Password:")
{
if (\preg_match('/^win/i', PHP_OS)) {
$vbscript = sys_get_temp_dir() . 'prompt_password.vbs';
file_put_contents(
$vbscript,
'wscript.echo(InputBox("'. \addslashes($text) . '", "", "password here"))'
);
$command = "cscript //nologo " . \escapeshellarg($vbscript);
$password = \rtrim(
\shell_exec($command)
);
\unlink($vbscript);
return $password;
} else {
$command = "/usr/bin/env bash -c 'echo OK'";
if (\rtrim(\shell_exec($command)) !== 'OK') {
throw new \Exception("Can't invoke bash");
}
$command = "/usr/bin/env bash -c 'read -s -p \"". addslashes($text). "\" mypassword && echo \$mypassword'";
$password = \rtrim(\shell_exec($command));
echo "\n";
return $password;
}
}
/**
* @return array
* @throws \Exception
*/
final protected function getSkyport(): array
{
$sp = $this->config['skyports'];
if (empty($sp)) {
throw new \Exception("No skyports configured");
}
if (\count($sp) === 1) {
$ret = \array_shift($sp);
return [
$ret['url'],
new SignaturePublicKey(
\Sodium\hex2bin($ret['public_key'])
)
];
}
$k = \array_keys($sp);
$i = $k[\random_int(0, \count($sp) - 1)];
$ret = $sp[$i];
return [
$ret['url'],
new SignaturePublicKey(
\Sodium\hex2bin($ret['public_key'])
)
];
}
/**
* Display the usage information for this command.
*
* @param array $args - CLI arguments
* @echo
*/
public function usageInfo(array $args = [])
{
$TAB = str_repeat(' ', self::TAB_SIZE);
$HTAB = str_repeat(' ', ceil(self::TAB_SIZE / 2));
echo $HTAB, 'Airship / Barge - ', $this->name, "\n\n";
echo $TAB, $this->description, "\n\n";
}
}
|