Skip to content

Instantly share code, notes, and snippets.

@pentagonal
Created June 5, 2017 20:47
Show Gist options
  • Save pentagonal/1734a6a320c1ea6a37f91deb5cc60e1d to your computer and use it in GitHub Desktop.
Save pentagonal/1734a6a320c1ea6a37f91deb5cc60e1d to your computer and use it in GitHub Desktop.
Just Simple Shell Arg Parser
<?php
namespace Pentagonal\RujakLegi;
/**
* Class Collection
* @package Pentagonal\RujakLegi
*/
class Collection implements \ArrayAccess, \IteratorAggregate, \Countable
{
/**
* @var array
*/
protected $data = [];
/**
* Collection constructor.
* @param array $args
*/
public function __construct(array $args = [])
{
$this->data = $args;
}
/**
* Set Value
*
* @param mixed $name
* @param mixed $value
*/
public function set($name, $value)
{
$this->data[$name] = $value;
}
/**
* Returnig Multiple
*
* @param array $keys
* @return array
*/
public function getMultiple(array $keys)
{
$retVal = [];
foreach ($keys as $value) {
$retVal[] = $this->get($value, false);
}
return $retVal;
}
/**
* Save Data
*/
public function save()
{
if (func_num_args() > 1) {
$this->set(func_get_arg(0), func_get_arg(1));
}
}
/**
* Replace content data
*
* @param array $replace
*/
public function replace(array $replace)
{
foreach ($replace as $key => $value) {
$this->set($key, $value);
}
}
/**
* Check if key exists
*
* @param mixed $name
* @return bool
*/
public function exist($name)
{
return array_key_exists($name, $this->data);
}
/**
* @param mixed $name
* @return bool
*/
public function exists($name)
{
return $this->exist($name);
}
/**
* @param mixed $key
*/
public function remove($key)
{
unset($this->data[$key]);
}
/**
* @param mixed $key
*/
public function delete($key)
{
$this->remove($key);
}
/**
* @return mixed
*/
public function pop()
{
return array_pop($this->data);
}
/**
* @return mixed
*/
public function shift()
{
return array_shift($this->data);
}
/**
* @param array $data
*/
public function prepend(array $data)
{
$this->data = $data + $this->data;
}
/**
* @param array $data
*/
public function append(array $data)
{
$this->data = $this->data + $data;
}
/**
* @param array $data
* @param mixed $_ optional
* @return int
*/
public function unshift($data, $_ = null)
{
if (func_num_args() > 1) {
return array_unshift($this->data, $data, $_);
}
return array_unshift($this->data, $data);
}
/**
* @param array $data
* @param mixed $_ optional
* @return int
*/
public function push($data, $_ = null)
{
if (func_num_args() > 1) {
return array_push($this->data, $data, $_);
}
return array_push($this->data, $data);
}
/**
* @return array
*/
public function values()
{
return array_values($this->data);
}
/**
* @return array
*/
public function data()
{
return $this->data;
}
/**
* @return array
*/
public function keys()
{
return array_keys($this->data);
}
/**
* @return mixed
*/
public function key()
{
return key($this->data);
}
/**
* @return mixed
*/
public function next()
{
return next($this->data);
}
/**
* @return mixed
*/
public function reset()
{
return reset($this->data);
}
/**
* @return mixed
*/
public function prev()
{
return prev($this->data);
}
/**
* @param int|null $numReq
* @return mixed
*/
public function rand($numReq = null)
{
if ($numReq) {
return array_rand($this->data);
}
return array_rand($this->data);
}
/**
* @param null|int $sort_flags
* @return bool
*/
public function sort($sort_flags = null)
{
return sort($this->data, $sort_flags);
}
/**
* @param null|int $sort_flags
* @return bool
*/
public function rsort($sort_flags = null)
{
return rsort($this->data, $sort_flags);
}
/**
* @param null|int $sort_flags
* @return bool
*/
public function ksort($sort_flags = null)
{
return ksort($this->data, $sort_flags);
}
/**
* @param null|int $sort_flags
* @return bool
*/
public function krsort($sort_flags = null)
{
return krsort($this->data, $sort_flags);
}
/**
* Get Data
*
* @param mixed $name
* @param mixed $default
* @return mixed
*/
public function get($name, $default = null)
{
return $this->exist($name)
? $this->data[$name]
: $default;
}
/**
* @param mixed $offset
* @return bool
*/
public function offsetExists($offset)
{
return $this->exist($offset);
}
/**
* @param mixed $offset
* @return mixed
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* @param mixed $offset
* @param mixed $value
*/
public function offsetSet($offset, $value)
{
$this->set($offset, $value);
}
/**
* @param mixed $offset
*/
public function offsetUnset($offset)
{
$this->remove($offset);
}
/**
* Clearing The Data
*/
public function clear()
{
$this->data = [];
}
/**
* @return int
*/
public function count()
{
return count($this->data);
}
/**
* @return bool
*/
public function isEmpty()
{
return $this->count() === 0;
}
/**
* Get If Values contains
*
* @param mixed $index
* @return mixed|null
*/
public function indexOf($index)
{
$key = array_search($index, $this->data, true);
return $key ? $this->get($key) : null;
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->data());
}
/**
* @return \Generator
*/
public function getGenerator()
{
yield $this->data();
}
}
<?php
namespace Pentagonal\RujakLegi;
/**
* Class ContextArgument
* @package Pentagonal\RujakLegi
*/
class ContextArgument implements \ArrayAccess
{
/**
* @var Collection
*/
protected $collection;
/**
* ContextArgument constructor.
* @param string $shortContext
* @param string $longContext
* @param bool $needAttribute
* @param string $description
* @param \Closure|null $callBack
*/
public function __construct(
$shortContext,
$longContext,
$needAttribute,
$description = '',
\Closure $callBack = null
) {
$this->collection = new Collection(
[
'short' => $shortContext,
'long' => $longContext,
'need_argument' => $needAttribute,
'description' => (is_string($description) ? $description : print_r($description, true)),
'callback' => $callBack
]
);
}
/**
* Get Short Name
*
* @return string
*/
public function getShort()
{
return $this->collection['short'];
}
/**
* Get Long Name
*
* @return string
*/
public function getLong()
{
return $this->collection['long'];
}
/**
* is Need Arguments
*
* @return bool
*/
public function getIsNeedArgument()
{
return $this->collection['need_argument'];
}
/**
* Get Context Description
*
* @return string
*/
public function getDescription()
{
return $this->collection['description'];
}
/**
* Get Closure Callback
*
* @return \Closure|null
*/
public function getCallback()
{
return $this->collection['callback'];
}
/**
* @return array|null
*/
public function getArguments()
{
return $this->collection['arguments'];
}
/**
* @param array $values
*/
public function setValues(array $values)
{
$this->collection->set('arguments', $values);
}
/**
* Clear Arguments Collection
*/
public function clearValues()
{
$this->collection->remove('arguments');
}
/**
* @param string $name
* @param mixed $default
* @return mixed
*/
public function get($name, $default = null)
{
return $this->collection->get($name, $default);
}
/**
* Get String
*
* @param string $name
* @return mixed
*/
public function __get($name)
{
return $this->collection->get($name);
}
/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
return $this->get($offset);
}
/**
* {@inheritdoc}
*/
public function offsetExists($offset)
{
return $this->collection->exist($offset);
}
/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{
// no operation
}
/**
* {@inheritdoc}
*/
public function offsetUnset($offset)
{
// no operation
}
}
<?php
namespace {
use Pentagonal\RujakLegi\ShellArguments;
class ExampleShell
{
/**
* @var ShellArguments
*/
protected $arg;
/**
* ExampleShell Constructor
*
* @param array $argv
*/
public function __construct(array $argv)
{
$this->arg = new ShellArguments(APP_NAME, $argv);
$c =& $this;
$this->arg
->setBanner(
<<<EOF
_ _ _ _ _ _ _ _ _ _
/ \ / \ / \ / \ / \ / \ / \ / \ / \ / \
( M | A | T | A | N | E | | I | K | U )
\_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
EOF
)
->showVersionBuild(true)
->onBeforeRun(function () use ($c) {
$c->showBeforeRun();
});
}
/**
* Run Context On Before Run
*/
protected function showBeforeRun()
{
echo "Hi....!\n";
}
/**
* @return ShellArguments
*/
public function run()
{
return $this
->process()
->arg
->run();
}
}
if (php_sapi() === 'cli') {
$exampleArg = new ExampleShell($argv);
// run
$shellArg = $exampleArg->run();
// do do do do do
}
}
<?php
namespace Pentagonal\RujakLegi;
/**
* Class ShellArguments
* @package Pentagonal\RujakLegi
*/
class ShellArguments
{
/**
* @var array
*/
protected $foreGroundColor = [
// Set up shell colors
'black' => '0;30',
'dark_gray' => '1;30',
'blue' => '0;34',
'light_blue' => '1;34',
'green' => '0;32',
'light_green'=> '1;32',
'cyan' => '0;36',
'light_cyan' => '1;36',
'red' => '0;31',
'light_red' => '1;31',
'purple' => '0;35',
'light_purple' => '1;35',
'brown' => '0;33',
'yellow' => '1;33',
'light_gray' => '0;37',
'white' => '1;37',
];
/**
* @var array
*/
protected $backgroundColors = [
'black' => '40',
'red' => '41',
'green' => '42',
'yellow' => '43',
'blue' => '44',
'magenta' => '45',
'cyan' => '46',
'light_gray' => '47',
];
const VERSION = '1.0-beta';
/**
* @var string|int
*/
protected $version;
/**
* @var string
*/
protected $banner;
/**
* @var string
*/
protected $appName;
/**
* @var string
*/
protected $file;
/**
* @var string
*/
protected $fileReal;
/**
* @var Database
*/
protected $db;
/**
* @var array
*/
protected $args;
/**
* @var array
*/
protected $argumentsOriginal;
/**
* @var Collection
*/
protected $validArguments;
/**
* @var Collection
*/
protected $ignoredArguments;
/**
* @var Collection[]|Collection
*/
protected $invalidArgumentsLists;
/**
* @var Collection|ContextArgument[]|array[]
*/
protected $allContextCollection;
/**
* @var array
*/
protected $contextKeyCollection = [];
/**
* @var bool
*/
protected $paused = false;
/**
* Auto Resume Time in Seconds
* @var int
*/
protected $autoResumeTime = 5;
/**
* @var bool
*/
protected $verbose = false;
/**
* @var bool
*/
protected $verboseDebug = false;
/**
* @var bool
*/
protected $quiet = false;
/**
* @var string
*/
protected $currentContext;
/**
* @var \Closure
*/
protected $onBeforeExecute;
/**
* @var \Closure
*/
protected $onAfterExecute;
/**
* @var \Closure
*/
protected $onBeforeRun;
/**
* @var \Closure
*/
protected $onAfterRun;
/**
* @var \Closure
*/
protected $onPause;
/**
* @var \Closure
*/
protected $onResume;
/**
* @var \Closure
*/
protected $onBeforeContext;
/**
* @var \Closure
*/
protected $onAfterContext;
/**
* @var float
*/
protected $timeStart;
/**
* @var int bytes memory usage
*/
protected $memoryStart;
/**
* @var string
*/
protected $infoUsage = '{{file}} [--options=[arguments]|-options [arguments]]';
/**
* @var int
*/
protected $tabIndent = 2;
/**
* @var bool
*/
protected $showVersionBuild = false;
/**
* Task constructor.
* @param string $appName
* @param array $argv
*/
public function __construct($appName, array $argv)
{
$this->setName($appName);
$this->args = $argv;
$this->argumentsOriginal = $argv;
$this->validArguments = new Collection();
$this->ignoredArguments = new Collection();
$this->invalidArgumentsLists = new Collection();
$this->version = static::VERSION;
$this->allContextCollection = new Collection([
'h' => new ContextArgument('h', 'help', false),
'q' => new ContextArgument('q', 'quiet', false),
'V' => new ContextArgument('V', 'version', false),
'v' => new ContextArgument('v', 'verbose', false),
'vv' => new ContextArgument('vv', 'debug', false),
]);
$this->init();
$this->timeStart = @microtime(true);
$this->memoryStart = \memory_get_usage(true);
}
/**
* @param string $status
* @return ShellArguments
*/
public function showVersionBuild($status)
{
$this->showVersionBuild = (bool) $status;
return $this;
}
/**
* Is Show Version Build
*
* @return bool
*/
public function isShownVersionBuild()
{
return (bool) $this->showVersionBuild;
}
/**
* @return array
*/
public function getArguments()
{
return $this->args;
}
/**
* @return array
*/
public function getOriginalArguments()
{
return $this->argumentsOriginal;
}
/**
* @return bool
*/
public function isCLIMode()
{
return php_sapi_name() == 'cli';
}
/**
* Get Phar
*
* @return string
* @throws \Exception
*/
public function getPhar()
{
static $phar;
if (isset($phar)) {
return $phar;
}
if (!class_exists('Phar')) {
throw new \Exception(
'Phar is not loaded by php',
E_ERROR
);
}
$phar = \Phar::running(false);
return $phar?: null;
}
/**
* @return array
*/
public function getPharSignature()
{
$PharFile = $this->getPhar();
if ($PharFile) {
$Phar = new \Phar(
$this->getPhar(),
\Phar::CURRENT_AS_FILEINFO || \Phar::FOLLOW_SYMLINKS
);
return $Phar->getSignature();
}
return null;
}
/**
* Initialize
*/
private function init()
{
$this
->setContext(
'V',
'version',
false,
'Show Application Version',
function () {
$additional = '';
if ($this->isShownVersionBuild()) {
$signature = $this->getPharSignature();
if (is_array($signature)) {
$hash = !empty($signature['hash'])
? strtolower($signature['hash'])
: null;
$type = !empty($signature['hash_type'])
? $signature['hash_type']
: null;
if ($hash) {
$hash = $this->color($hash, 'brown');
$additional = " build {$hash}";
$type = $type
? ' '. $this->color("[{$type}]", 'blue')
: '';
$additional .= $type;
}
}
}
$this
->show(
(
$this->color($this->getName(), 'green')
. ' version ' .
$this->color($this->getVersion(), 'brown')
. $additional
),
true
)
->stop(0);
}
)
->setContext(
'h',
'help',
false,
'Display this help message.',
function () {
$this
->show($this->getBanner(), true)
->show(
(
$this->color($this->getName(), 'green')
. ' version ' .
$this->color($this->getVersion(), 'brown')
),
true
)
->newLine()
->show(
$this->color('Usage : ', 'brown'),
true
)
->indent()
->show(
// show usage
str_replace(
[
'{{file}}',
'{{file.real}}'
],
[
$this->getFile(),
$this->getRealFile()
],
print_r($this->infoUsage, true)
),
true
)
->newLine()
->show(
$this->color('Options : ', 'brown'),
true
);
$allContext = $this->getAllContext();
$longest = 0;
foreach ($allContext as $value) {
$contextString = '-'
. $value->getShort()
. ', --'
. $value->getLong();
$length = strlen($contextString);
if ($longest < $length) {
$longest = $length;
}
}
$longest += 2;
foreach ($allContext as $value) {
$contextString = '-'
. $value->getShort()
. ', --'
. $value->getLong();
$length = strlen($contextString);
$length = $longest - $length;
$this
->indent()
->show(
$this->color($contextString, 'green')
)
->indent($length)
->show($value->getDescription(), true);
if ($value->getIsNeedArgument()) {
$this
->indent($longest+2)
->show(
'-' . $value->getShort() . ' [arguments], ',
true
)
->indent($longest+2)
->show(
'--' . $value->getLong() .'=[arguments]',
true
);
}
}
$this
->newLine()
->stop(0);
}
)
->setContext(
'v',
'verbose',
false,
'Show verbose mode on application'
)
->setContext(
'vv',
'debug',
false,
'Debug mode, display all debug with verbose mode'
)
->setContext(
'q',
'quiet',
false,
'Do not output any message'
);
}
/**
* All Context Collection
*
* @return Collection|ContextArgument[]
*/
public function getAllContext()
{
return $this->allContextCollection;
}
/**
* Get Path File executed
* @return string
*/
public function getFile()
{
return $this->file;
}
/**
* Get RealPath File executed
*
* @return string
*/
public function getRealFile()
{
return $this->fileReal;
}
/**
* Create Interactive
*
* @param \Closure $closure
* @return bool|mixed
*/
public function interactiveLoop(
\Closure $closure
) {
$last_line = false;
if ($closure instanceof \Closure) {
$fp = @fopen('php://stdin', 'r');
while (!$last_line) {
$next_line = fgets($fp, 512); // read the special file to get the user input from keyboard
$stopped = null;
$closureCallback = $closure->bindTo($this);
$closureCallbackRetVal = $closureCallback($next_line, $stopped);
if ($stopped || !is_bool($stopped)) {
if ($fp) {
@fclose($fp);
$fp = null;
}
return $closureCallbackRetVal;
}
}
if ($fp) {
@fclose($fp);
}
}
return false;
}
/**
* @param string $data
* @param bool $withNewLine
* @return ShellArguments
*/
public function show($data, $withNewLine = false)
{
$data = print_r($data, true);
echo $data;
$this->newLine($withNewLine ? 1 : 0);
return $this;
}
/**
* Create New Line
*
* @param int $count
* @return ShellArguments
*/
public function newLine($count = 1)
{
if (!is_numeric($count)) {
return $this;
}
$count = abs(intval($count));
$count = $count > 0 ? $count : 0;
echo ($count ? str_repeat(PHP_EOL, $count) : '');
return $this;
}
/**
* Indentation count
*
* @param int $count
* @return ShellArguments
*/
public function indent($count = null)
{
if ($count === null) {
$count = $this->getTabIndent();
}
if (!is_numeric($count)) {
return $this;
}
$count = abs(intval($count));
$count = $count > 0 ? $count : 0;
echo ($count ? str_repeat(' ', $count) : '');
return $this;
}
/**
* Create Colorize
*
* @param string $string
* @param null|string $foreground_color
* @param null|string $background_color
* @return string
*/
public function color($string, $foreground_color = null, $background_color = null)
{
$string = print_r($string, true);
$colored_string = "";
/**
* Check if given foreground color found
*/
if ($foreground_color && isset($this->foreGroundColor[$foreground_color])) {
$colored_string .= "\033[" . $this->foreGroundColor[$foreground_color] . "m";
}
/**
* Check if given background color found
*/
if ($background_color && isset($this->backgroundColors[$background_color])) {
$colored_string .= "\033[" . $this->backgroundColors[$background_color] . "m";
}
// Add string and end coloring
$colored_string .= $string . "\033[0m";
return $colored_string;
}
/**
* Set Application Name
*
* @param string $name
* @return ShellArguments
*/
public function setName($name)
{
if (!is_string($name) && !is_numeric($name)) {
throw new \InvalidArgumentException(
sprintf(
'Application Name must be as a string %s given',
gettype($name)
)
);
}
$this->appName = $name;
return $this;
}
/**
* Get Application Name
*
* @return string
*/
public function getName()
{
return $this->appName;
}
/**
* Set Tab Indent for help
*
* @param int $count
* @return ShellArguments
*/
public function setIndent($count = 4)
{
if (!is_numeric($count)) {
return $this;
}
$this->tabIndent = abs(intval($count));
$this->tabIndent = $this->tabIndent < 0 ? $this->tabIndent : 0;
return $this;
}
/**
* @return int
*/
public function getTabIndent()
{
return $this->tabIndent;
}
/**
* Set Description
* you can create custom banner on
* @link http://www.network-science.de/ascii/
*
* @param string $banner
* @return ShellArguments
*/
public function setBanner($banner)
{
if (!is_string($banner)) {
$banner = print_r($banner);
}
$this->banner = $banner;
return $this;
}
/**
* Get description stored
*
* @return string
*/
public function getBanner()
{
return $this->banner;
}
/**
* @param string $version
* @return ShellArguments
*/
public function setVersion($version)
{
$this->version = $version;
return $this;
}
/**
* Get Version
*
* @return int|string
*/
public function getVersion()
{
return $this->version;
}
/**
* Get Valid Arguments
*
* @return Collection
*/
public function getValidArguments()
{
return $this->validArguments;
}
/**
* Get Ignored Arguments
*
* @return Collection
*/
public function getIgnoreArguments()
{
return $this->ignoredArguments;
}
/**
* @return Collection
*/
public function getInvalidArgumentsValuable()
{
return $this->invalidArgumentsLists;
}
/**
* Get Context
*
* @param $short
* @return array|mixed|null|ContextArgument
*/
public function getContext($short)
{
if (!$short || !is_string($short)) {
return null;
}
if (isset($this->allContextCollection[$short])) {
return $this->allContextCollection[$short];
}
if (isset($this->contextKeyCollection[$short])) {
return isset($this->allContextCollection[$this->contextKeyCollection[$short]])
? $this->allContextCollection[$this->contextKeyCollection[$short]]
: null;
}
return null;
}
/**
* Get Context Name for name
*
* @param string $short
* @return string|null
*/
public function getContextNameFor($short)
{
$context = $this->getContext($short);
if (!$context) {
return null;
}
return $context->getLong();
}
/**
* Get Short context name
*
* @param string $short
* @return string|null
*/
public function getContextShort($short)
{
$context = $this->getContext($short);
if (!$context) {
return null;
}
return $context->getShort();
}
/**
* Is Context need Arguments Value
*
* @param string $short
* @return bool|null
*/
public function getContextNeedArguments($short)
{
$context = $this->getContext($short);
if (!$context) {
return null;
}
return (bool) $context->getIsNeedArgument();
}
/**
* Get Context Description
*
* @param string $short
* @return string|null
*/
public function getContextDescription($short)
{
$context = $this->getContext($short);
if (!$context) {
return null;
}
return $context->getDescription();
}
/**
* Get Context Callback
*
* @param string $short
* @return \Closure|bool|null
*/
public function getContextCallback($short)
{
$context = $this->getContext($short);
if (!$context) {
return null;
}
return $context->getCallback()?: false;
}
/**
* Get Context Name currently In Progress
*
* @return string
*/
public function getCurrentContextName()
{
return $this->currentContext;
}
/**
* Get Context Name currently In Progress
*
* @return string
*/
public function getCurrentContext()
{
$context = $this->getContext($this->getCurrentContextName());
return $context ?: null;
}
/**
* Stop Execution
*
* @return ShellArguments
*/
public function pause()
{
$this->paused = false;
return $this;
}
/**
* Resume Exec
*
* @return ShellArguments
*/
public function resume()
{
$this->paused = false;
return $this;
}
/**
* Check if on pause
*
* @return bool
*/
public function isPaused()
{
return $this->paused;
}
/**
* Stop CLI
* @param int $code
*/
public function stop($code = 0)
{
exit($code);
}
/**
* @param string $short
* @return bool
*/
public function isContextExists($short)
{
return (bool) $this->getContext($short);
}
/**
* @param string $short
* @param \Closure $closure
* @return ShellArguments
* @throws \InvalidArgumentException
*/
public function setCallback($short, \Closure $closure)
{
if ($this->isContextExists($short)) {
if (isset($this->allContextCollection[$short])) {
$this->allContextCollection[$short][2] = $closure;
} elseif (isset($this->contextKeyCollection[$short])) {
isset($this->allContextCollection[$this->contextKeyCollection[$short]]) &&
$this->allContextCollection[$this->contextKeyCollection[$short]] = $closure;
}
return $this;
}
throw new \InvalidArgumentException(
sprintf('Context %s is not exists!', $short),
E_USER_ERROR
);
}
/**
* @param string $short
* @param string $long
* @param bool $needValue
* @param string $description
* @param \Closure|null $closure
* @return ShellArguments
*/
public function setContext(
$short,
$long,
$needValue = false,
$description = '',
\Closure $closure = null
) {
if (!$closure) {
$this->allContextCollection[$short] = new ContextArgument(
$short,
$long,
(bool)$needValue,
$description
);
return $this;
}
$this->allContextCollection[$short] = new ContextArgument(
$short,
$long,
(bool)$needValue,
$description,
$closure
);
return $this;
}
/**
* Parse Arguments CLI
* @return ShellArguments
*/
protected function parseArguments()
{
$this->args = $this->argumentsOriginal;
$this->file = array_shift($this->args);
$this->fileReal = realpath($this->file)?: $this->file;
return $this->parseCommand();
}
/**
* Parse The ARGS command
*/
protected function parseCommand()
{
$lastCommand = null;
$lastCommandLatest = $lastCommand;
$args = $this->args;
$aliases_key = [];
/**
* @var ContextArgument $value
*/
foreach ($this->allContextCollection as $key => $value) {
$name = $value->getLong();
$aliases_key[$name] = [$key, $value->getIsNeedArgument()];
$this->contextKeyCollection[$name] = $key;
}
/**
* Parse Arguments
*/
foreach ($args as $value) {
if (! $lastCommand) {
if ($value && $value[0] == '-') {
if (preg_match('`(?P<pos>[\-]{1,2})(?P<name>[a-z0-9\-\_]+)?\=(?P<value>.*?)$`i', $value, $match)
&& !empty($match['name'])
) {
$length_pos = strlen($match['pos']);
$name = $match['name'];
if ($length_pos === 1) {
$named = isset($this->allContextCollection[$name])
? $this->allContextCollection[$name]->getLong()
: null;
} else {
$named = isset($aliases_key[$name])
? $name
: null;
}
if ($named) {
$this->validArguments[$named] = $match['value'];
} else {
$this->ignoredArguments[$name] = $match['value'];
}
continue;
}
if (preg_match('`(?P<pos>[\-]{1,2})(?P<name>[a-z0-9\-\_]+)`i', $value, $matches)) {
$length_pos = strlen($matches['pos']);
$name = $matches['name'];
$isNeedValue = null;
if ($length_pos === 1) {
$named = isset($this->allContextCollection[$name])
? $this->allContextCollection[$name]->getLong()
: null;
} else {
$named = isset($aliases_key[$name])
? $name
: null;
}
if ($named && !empty($aliases_key[$named][1])) {
$isNeedValue = true;
}
$lastCommandLatest = $named?:$name;
if ($isNeedValue) {
$lastCommand = $named;
continue;
}
if ($named) {
$this->validArguments[$lastCommandLatest] = null;
} else {
if (!isset($this->invalidArgumentsLists[$lastCommandLatest])) {
$this->invalidArgumentsLists[$lastCommandLatest] = new Collection();
}
}
}
continue;
}
if (!isset($this->invalidArgumentsLists[$lastCommandLatest])) {
$this->invalidArgumentsLists[$lastCommandLatest] = new Collection();
}
if (isset($this->ignoredArguments[$lastCommandLatest])) {
$this->invalidArgumentsLists[$lastCommandLatest]->push($value);
}
}
if (isset($aliases_key[$lastCommand])) {
$this->validArguments[$lastCommand] = $value;
} else {
if (!isset($this->ignoredArguments[$lastCommandLatest])) {
if (!isset($this->invalidArgumentsLists[$lastCommandLatest])) {
$this->invalidArgumentsLists[$lastCommandLatest] = new Collection();
}
$this->invalidArgumentsLists[$lastCommandLatest]->push($value);
}
}
$lastCommand = null;
}
return $this;
}
/**
* Set Auto Resume Time In second
*
* @param int $second
* @return ShellArguments
* @throws \InvalidArgumentException
*/
public function setAutoResume($second)
{
if (!is_numeric($second)) {
throw new \InvalidArgumentException(
"Time to auto resume must be as a numeric values!"
);
}
$this->autoResumeTime = abs($second);
$this->autoResumeTime = $this->autoResumeTime < 0
? 0
: (
$this->autoResumeTime < 30 // max 30 seconds
? 30
: $this->autoResumeTime
);
return $this;
}
/**
* @return int|float
*/
public function getAutoResumeTime()
{
return $this->autoResumeTime;
}
/**
* Callback call when before run
*
* @param \Closure $closure
* @return ShellArguments
*/
public function onBeforeRun(\Closure $closure)
{
$this->onBeforeRun = $closure;
return $this;
}
/**
* Callback call when after all run
*
* @param \Closure $closure
* @return ShellArguments
*/
public function onAfterRun(\Closure $closure)
{
$this->onAfterRun = $closure;
return $this;
}
/**
* Callback call when before execute
*
* @param \Closure $closure
* @return ShellArguments
*/
public function onBeforeExecute(\Closure $closure)
{
$this->onBeforeExecute = $closure;
return $this;
}
/**
* Callback call when after all execute
*
* @param \Closure $closure
* @return ShellArguments
*/
public function onAfterExecute(\Closure $closure)
{
$this->onAfterExecute = $closure;
return $this;
}
/**
* Callback Call when Paused Each Procedure
*
* @param \Closure $closure
* @return ShellArguments
*/
public function onPause(\Closure $closure)
{
$this->onPause = $closure;
return $this;
}
/**
* Callback Call when Resume Each Procedure
*
* @param \Closure $closure
* @return ShellArguments
*/
public function onResume(\Closure $closure)
{
$this->onResume = $closure;
return $this;
}
/**
* @param \Closure $closure
* @return ShellArguments
*/
public function beforeRunningContext(\Closure $closure)
{
$this->onBeforeContext = $closure;
return $this;
}
/**
* @param \Closure $closure
* @return ShellArguments
*/
public function afterRunningContext(\Closure $closure)
{
$this->onAfterContext = $closure;
return $this;
}
/**
* @param int $code
*/
private function internalShowVersion($code = 0)
{
$context = $this->getContext('version');
$callback = $context->getCallBack();
$this->currentContext = 'version';
if ($callback instanceof \Closure) {
$callback($context);
}
$this->stop($code);
}
/**
* @param int $code
*/
private function internalShowHelp($code = 0)
{
$context = $this->getContext('help');
$callback = $context->getCallBack();
$this->currentContext = 'help';
if ($callback instanceof \Closure) {
$callback($context);
}
$this->stop($code);
}
/**
* @return bool
*/
public function isDebug()
{
return $this->verboseDebug;
}
/**
* @return bool
*/
public function isVerbose()
{
return $this->verbose;
}
/**
* @return bool
*/
public function isQuiet()
{
return $this->quiet;
}
/**
* Run Application
*
* @return ShellArguments
*/
public function run()
{
// re - set again
$this->timeStart = @microtime(true);
$this->memoryStart = \memory_get_usage(true);
// doing parse
$this->parseArguments();
// get arguments call
$args = $this->getValidArguments();
/**
* debug & verbose
*/
$this->verboseDebug = $args->exist('debug');
$this->verbose = $this->verboseDebug || $args->exist('verbose');
$this->quiet = $args->exist('quiet');
// remove unused
unset($args['debug'], $args['verbose'], $args['quiet']);
if ($this->onBeforeExecute instanceof \Closure) {
$beforeExecute = $this->onBeforeExecute->bindTo($this);
$beforeExecute();
}
if ($args->exist('version')) {
$this->internalShowVersion();
return $this;
}
$the_arguments = $this->getArguments();
if (empty($the_arguments) || $args->exist('help')) {
$this->internalShowHelp(0);
return $this;
}
if ($args->isEmpty()) {
$argument = $this->args;
$current = '';
foreach ($argument as $value) {
if (in_array(
ltrim($value, '-'),
['v', 'V', 'vv', 'version', 'verbose', 'debug', 'help', 'h'])
) {
continue;
}
$current = $value;
break;
}
if ($current) {
$this
->newLine()
->show('[')
->indent()
->show(
$this->color('Invalid Option ', null, 'red')
. ' : '
. $this->color($current, 'blue'),
false
)
->indent()
->show(']', true)
->internalShowHelp(1);
} else {
$this->internalShowHelp(0);
}
}
unset($args['help'], $args['version']);
if ($this->onBeforeRun instanceof \Closure) {
$beforeRun = $this->onBeforeRun->bindTo($this);
$beforeRun();
}
foreach ($args as $key => $value) {
if (isset($this->contextKeyCollection[$key])) {
$this->currentContext = $key;
$context = $this->allContextCollection[$this->contextKeyCollection[$key]];
$valueContext = [$value];
if (isset($this->invalidArgumentsLists[$key])
&& !$this->invalidArgumentsLists[$key]->isEmpty()
) {
$data = clone $this->invalidArgumentsLists[$key];
$data->unshift($value);
$valueContext = $data->data();
}
$context->setValues($valueContext);
if ($this->onBeforeContext instanceof \Closure) {
$before = $this->onBeforeContext->bindTo($this);
$before(clone $context);
}
if ($context['callback'] instanceof \Closure) {
$callback = $context['callback']->bindTo($this);
$callback(clone $context);
}
// after context
if ($this->onAfterContext instanceof \Closure) {
$after = $this->onAfterContext->bindTo($this);
$after(clone $context);
}
$hasResume = false;
// paused
if ($this->isPaused()) {
$hasResume = true;
if ($this->onPause instanceof \Closure) {
$pause = $this->onPause->bindTo($this);
$pause(clone $context);
}
}
// if still paused
if ($this->paused) {
if ($this->autoResumeTime > 0) {
sleep($this->autoResumeTime);
}
$this->resume();
}
// if contains paused & go resume
if ($hasResume && $this->onResume instanceof \Closure) {
$resume = $this->onResume->bindTo($this);
$resume(clone $context);
}
}
}
if ($this->onAfterRun instanceof \Closure) {
$afterRun = $this->onAfterRun->bindTo($this);
$afterRun();
}
if ($this->onAfterExecute instanceof \Closure) {
$onAfterExecute = $this->onAfterExecute->bindTo($this);
$onAfterExecute();
}
return $this;
}
}
@pentagonal
Copy link
Author

pentagonal commented Jun 5, 2017

Packing As Phar

fileName : box.json

{
  "alias": "application",
  "compactors": [
    "Herrera\\Box\\Compactor\\Composer",
    "Herrera\\Box\\Compactor\\Json"
  ],
  "compression": "GZ",
  "main": "binaryDirectory/application",
  "output": "build/application.phar",
  "finder": [
    {
      "exclude": ["Tests", "Test", "tests", "test", "box.phar", "composer.lock", "application.phar", "Data"],
      "in": ["vendor", "sourceCodeDirectory", "binaryDirectory"]
    }
  ],
  "files" : [
        "Add The Files",
        "Add The Files Again"
    ],
  "chmod": "0755",
  "stub": true
}

fileName : build-phar.sh

#!/usr/bin/env bash

if [ -f composer.lock ]; then
  rm composer.lock
fi

composer install --no-dev --optimize-autoloader

mkdir -p build

if [ ! -f box.phar ]; then
    wget https://github.com/box-project/box2/releases/download/2.6.0/box-2.6.0.phar -O box.phar
fi

/usr/bin/env php box.phar build -vv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment