Skip to content

Commit

Permalink
fix: next is option value check error
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Jan 25, 2022
1 parent 6822123 commit df8d27b
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 43 deletions.
1 change: 0 additions & 1 deletion src/Concern/RuleParserTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ public function addOptsByRules(array $rules): void
public function addOptByRule(string $name, array|string $rule): static
{
$this->optRules[$name] = $rule;

return $this;
}

Expand Down
26 changes: 10 additions & 16 deletions src/FlagUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,21 @@ public static function isOptionValue(mixed $val): bool
return false;
}

// if is: '', 0
if (!$val) {
// if is: '', 0 || is not option name
if (!$val || $val[0] !== '-') {
return true;
}

// is not option name.
if ($val[0] !== '-') {
// ensure is option value.
if (!str_contains($val, '=')) {
return true;
}

// is string value, but contains '='
[$name,] = explode('=', $val, 2);

// named argument OR invalid: 'some = string'
return false === self::isValidName($name);
// ensure is option value.
if (!str_contains($val, '=')) {
return true;
}

// is option name.
return false;
// is string value, but contains '='
[$name,] = explode('=', $val, 2);

// named argument OR invalid: 'some = string'
return false === self::isValidName($name);
}

/**
Expand Down
29 changes: 18 additions & 11 deletions src/Flags.php
Original file line number Diff line number Diff line change
Expand Up @@ -362,39 +362,46 @@ public function bindingArguments(): self
}

// parse arguments
$args = $this->parseRawArgs($this->rawArgs);
$args = $this->parseRawArgs($remains = $this->rawArgs);

// collect argument values
foreach ($this->arguments as $index => $arg) {
if (!isset($args[$index])) {
$name = $arg->getName();

if (isset($args[$name])) {
$value = $args[$name];
unset($args[$name]);
} elseif (isset($args[$index])) {
$value = $args[$index];
unset($args[$index]);
} else {
if ($arg->isRequired()) {
$mark = $arg->getNameMark();
throw new FlagException("flag argument $mark is required");
}
continue;
}

// collect all remain args
// array: collect all remain args
if ($arg->isArray()) {
foreach ($args as $value) {
$arg->setValue($value);
}
$args = [];
$remains = $args = [];
} else {
$arg->setValue($args[$index]);
unset($args[$index]);
array_shift($remains);
$arg->setValue($value);
}
}

if ($args) {
$args = array_values($args);

if ($remains) {
$remains = array_values($remains);
if ($this->strictMatchArgs) {
throw new FlagException(sprintf('unknown arguments (error: "%s").', implode(' ', $args)));
throw new FlagException(sprintf('unknown arguments (error: "%s").', implode(' ', $remains)));
}
}

$this->remainArgs = $args;
$this->remainArgs = $remains;
return $this;
}

Expand Down
14 changes: 12 additions & 2 deletions src/FlagsParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -498,13 +498,23 @@ public function popFirstRawArg(): string
/**
* @return array
*/
public function getInfo(): array
public function getInfo(bool $more = false): array
{
return [
$info = [
'flags' => $this->flags,
'rawArgs' => $this->rawArgs,
'remainArgs' => $this->remainArgs,
'opts' => $this->getOpts(),
'args' => $this->getArgs(),
];

if ($more) {
$info['optRules'] = $this->getOptRules();
$info['argRules'] = $this->getArgRules();
$info['aliases'] = $this->getAliases();
}

return $info;
}

/**
Expand Down
28 changes: 16 additions & 12 deletions src/SFlags.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Toolkit\PFlag\Exception\FlagParseException;
use Toolkit\Stdlib\OS;
use Toolkit\Stdlib\Str;
use function array_shift;
use function array_values;
use function count;
use function current;
Expand Down Expand Up @@ -540,7 +541,7 @@ protected function setRealOptValue(string $name, mixed $value, array $define): v
public function bindingArguments(): void
{
// parse arguments
$args = $this->parseRawArgs($this->rawArgs);
$args = $this->parseRawArgs($remains = $this->rawArgs);

// check and collect argument values
foreach ($this->argDefines as $index => $define) {
Expand All @@ -550,36 +551,39 @@ public function bindingArguments(): void
$required = $define['required'];
$isArray = FlagType::isArray($define['type']);

if (!isset($args[$index])) {
if (isset($args[$name])) {
$value = $args[$name];
unset($args[$name]);
} elseif (isset($args[$index])) {
$value = $args[$index];
unset($args[$index]);
} else {
if ($required) {
throw new FlagException("flag argument $mark is required");
}
continue;
}

// collect value
// array: collect all remain args
if ($isArray) {
// remain args
foreach ($args as $arrValue) {
$this->collectArgValue($arrValue, $index, true, $define);
}
$args = [];
$remains = $args = [];
} else {
$value = $args[$index];
array_shift($remains);
$this->collectArgValue($value, $index, false, $define);
unset($args[$index]);
}
}

if ($args) {
$args = array_values($args);

if ($remains) {
$remains = array_values($remains);
if ($this->strictMatchArgs) {
throw new FlagException(sprintf('unknown arguments (error: "%s").', implode(', ', $args)));
throw new FlagException(sprintf('unknown arguments (error: "%s").', implode(', ', $remains)));
}
}

$this->remainArgs = $args;
$this->remainArgs = $remains;
}

/**
Expand Down
10 changes: 10 additions & 0 deletions test/BaseFlagsTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
use Toolkit\PFlag\Flags;
use Toolkit\PFlag\FlagsParser;
use Toolkit\PFlag\SFlags;
use Toolkit\Stdlib\Php;
use function in_array;

/**
* Class BaseTestCase
Expand All @@ -41,6 +43,14 @@ protected function runAndGetException(callable $cb, ...$args): Throwable
return new RuntimeException('NO ERROR');
}

public function assertArrayHasValue($needle, array $arr, string $message = ''): void
{
$has = in_array($needle, $arr, true);
$msg = 'The array ' . Php::toString($arr) . ' should contains: ' . $needle;

$this->assertTrue($has, $message ?: $msg);
}

/**
* @param Closure $testFunc
*/
Expand Down
43 changes: 42 additions & 1 deletion test/FlagsParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use InvalidArgumentException;
use Toolkit\PFlag\Exception\FlagException;
use Toolkit\PFlag\FlagsParser;
use Toolkit\PFlag\FlagType;
use function get_class;

/**
Expand Down Expand Up @@ -138,11 +139,21 @@ private function doCheckStopOnTwoHl(FlagsParser $fs): void
$ok = $fs->parse(['--name', 'inhere', 'val0']);
$this->assertTrue($ok);
$this->assertSame('val0', $fs->getArg('arg0'));

$fs->resetResults();

$ok = $fs->parse(['--name', 'inhere', '--', '--val0']);
$this->assertTrue($ok);
$this->assertSame('--val0', $fs->getArg('arg0'));
$fs->resetResults();

$ok = $fs->parse(["--", "-e", "dev", "-v", "port=3455"]);
$this->assertTrue($ok);
$this->assertNotEmpty($fs->getArgs());
$this->assertSame('-e', $fs->getArg('arg0'));

$otherArgs = $fs->getRemainArgs();
$this->assertArrayHasValue('port=3455', $otherArgs);
$fs->resetResults();
}

public function testStopOnFirstArg(): void
Expand Down Expand Up @@ -404,4 +415,34 @@ private function doCheckSetOptAndSetArg($fs): void
$this->assertSame(FlagException::class, get_class($e));
$this->assertSame("flag argument 'not-exist-arg' is undefined", $e->getMessage());
}

public function testParse_opt_isKV(): void
{
foreach ($this->createParsers() as $fs) {
$this->doTestParse_opt_isKV($fs);
}
}

public function doTestParse_opt_isKV(FlagsParser $fs): void
{
$fs->addOptsByRules([
'env, e' => [
'type' => FlagType::STRING,
'required' => true,
],
'vars,var,v' => [
'type' => FlagType::ARRAY,
'desc' => 'can append some extra vars, format: KEY=VALUE',
],
]);

$flags = ['-e', 'dev', '--var', 'key0=val0', '-v', 'port=3445'];
$fs->parse($flags);

$this->assertNotEmpty($fs->getOpts());
$this->assertNotEmpty($fs->getInfo(true));
$this->assertEquals('vars', $fs->resolveAlias('v'));
$this->assertEquals('vars', $fs->resolveAlias('var'));
$this->assertEquals(['key0=val0', 'port=3445'], $fs->getOpt('vars'));
}
}

0 comments on commit df8d27b

Please sign in to comment.