11
0
Fork 0
mirror of https://github.com/n3w/helpers-cli-input.git synced 2025-12-19 12:43:23 +00:00

Initial commit

This commit is contained in:
Alannah Kearney 2019-05-20 15:08:41 +10:00
commit 0620d00f08
24 changed files with 1054 additions and 0 deletions

174
src/Input/Handlers/Argv.php Normal file
View file

@ -0,0 +1,174 @@
<?php
declare(strict_types=1);
namespace pointybeard\Helpers\Cli\Input\Handlers;
use pointybeard\Helpers\Cli\Input;
use pointybeard\Helpers\Functions\Flags;
class Argv extends Input\AbstractInputHandler
{
private $argv = null;
const OPTION_LONG = 'long';
const OPTION_SHORT = 'short';
const ARGUMENT = 'argument';
public function __construct(array $argv = null)
{
if (null === $argv) {
$argv = $_SERVER['argv'];
}
// Remove the script name
array_shift($argv);
$this->argv = self::expandOptions($argv);
}
/**
* This will look for combined options, e.g -vlt and expand them to -v -l -t.
*/
protected static function expandOptions(array $args): array
{
$result = [];
foreach ($args as $a) {
switch (self::findType($a)) {
case self::OPTION_SHORT:
// If the name is longer than a 2 characters
// it will mean it's a combination of flags. e.g.
// -vlt 12345 is the same as -v -l -t 12345
if (strlen($a) > 2) {
// Strip the leading hyphen (-)
$a = substr($a, 1);
for ($ii = 0; $ii < strlen($a); ++$ii) {
$result[] = "-{$a[$ii]}";
}
break;
}
// no break
default:
$result[] = $a;
break;
}
}
return $result;
}
protected function parse(): bool
{
// So some parsing here.
$it = new \ArrayIterator($this->argv);
$position = 0;
while ($it->valid()) {
$token = $it->current();
switch (self::findType($token)) {
case self::OPTION_LONG:
$opt = substr($token, 2);
if (false !== strstr($opt, '=')) {
list($name, $value) = explode('=', $opt, 2);
} else {
$name = $opt;
$value = true;
}
$o = $this->collection->findOption($name);
$this->options[
$o instanceof Input\AbstractInputType
? $o->name()
: $name
] = $value;
break;
case self::OPTION_SHORT:
$name = substr($token, 1);
// Determine if we're expecting a value.
// It also might have a long option equivalent, so we need
// to look for that too.
$o = $this->collection->findOption($name);
// This could also be an incrementing value
// and needs to be added up. E.g. e.g. -vvv or -v -v -v
// would be -v => 3
if ($o instanceof Input\AbstractInputType && Flags\is_flag_set($o->flags(), Input\AbstractInputType::FLAG_TYPE_INCREMENTING)) {
$value = isset($this->options[$name])
? $this->options[$name] + 1
: 1
;
// Not incrementing, so resume default behaviour
} else {
// We'll need to look ahead and see what the next value is.
// Ignore it if the next item is another option
// Advance the pointer to grab the next value
$it->next();
$value = $it->current();
// See if the next item is another option and of it is,
// rewind the iterator and set value to 'true'. Also,
// if this option doesn't expect a value (no FLAG_VALUE_REQUIRED or FLAG_VALUE_OPTIONAL flag set), don't capture the next value.
if (null === $value || self::isOption($value) || !($o instanceof Input\AbstractInputType) || (
!Flags\is_flag_set($o->flags(), Input\AbstractInputType::FLAG_VALUE_REQUIRED) && !Flags\is_flag_set($o->flags(), Input\AbstractInputType::FLAG_VALUE_OPTIONAL)
)) {
$value = true;
$it->seek($position);
}
}
$this->options[
$o instanceof Input\AbstractInputType
? $o->name()
: $name
] = $value;
break;
case self::ARGUMENT:
default:
// Arguments are positional, so we need to keep a track
// of the index and look at the collection for an argument
// with the same index
$a = $this->collection->getArgumentsByIndex(count($this->arguments));
$this->arguments[
$a instanceof Input\AbstractInputType
? $a->name()
: count($this->arguments)
] = $token;
break;
}
$it->next();
++$position;
}
return true;
}
private static function isOption(string $value): bool
{
return '-' == $value[0];
}
private static function findType(string $value): string
{
if (0 === strpos($value, '--')) {
return self::OPTION_LONG;
} elseif (self::isOption($value)) {
return self::OPTION_SHORT;
} else {
return self::ARGUMENT;
}
}
}