Skip to content

Commit 42f576a

Browse files
feat: add static factory methods for options and arguments
1 parent 64011bf commit 42f576a

File tree

7 files changed

+61
-14
lines changed

7 files changed

+61
-14
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
/vendor/
2-
/.idea
2+
/.idea
3+
composer.lock

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"require": {
1212
"php": ">=7.4",
1313
"ext-mbstring": "*",
14-
"ext-json": "*"
14+
"ext-json": "*",
15+
"ext-ctype": "*"
1516
},
1617
"require-dev": {
1718
"phpdevcommunity/unitester": "^0.1.0@alpha"

src/Argument/CommandArgument.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,20 @@ final class CommandArgument
99
private $defaultValue;
1010
private ?string $description;
1111

12-
public function __construct(string $name, bool $isRequired = false, $defaultValue = null, ?string $description = null)
12+
public function __construct(string $name, bool $isRequired = false, $defaultValue = null, ?string $description = null)
1313
{
14-
$this->name = $name;
14+
if ($name === '') {
15+
throw new \InvalidArgumentException("Option name cannot be empty.");
16+
}
17+
if (!ctype_alpha($name)) {
18+
throw new \InvalidArgumentException("Option name must contain only letters. '$name' is invalid.");
19+
}
20+
21+
if ($isRequired && $defaultValue !== null) {
22+
throw new \LogicException("Argument '$name' cannot be required and have a default value.");
23+
}
24+
25+
$this->name = strtolower($name);
1526
$this->isRequired = $isRequired;
1627
$this->defaultValue = $defaultValue;
1728
$this->description = $description;
@@ -47,4 +58,13 @@ public function getDescription(): ?string
4758
return $this->description;
4859
}
4960

61+
public static function required(string $name, ?string $description = null): self
62+
{
63+
return new self($name, true, null, $description);
64+
}
65+
66+
public static function optional(string $name, $default = null, ?string $description = null): self
67+
{
68+
return new self($name, false, $default, $description);
69+
}
5070
}

src/CommandRunner.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,14 @@ private function execute(CommandInterface $command, CommandParser $commandParser
140140

141141
$arguments = $command->getArguments();
142142
foreach ($arguments as $key => $argument) {
143-
$key = strval($key);
144-
if ($argument->isRequired() && empty($commandParser->getArgumentValue($key))) {
143+
$key = $argument->getName();
144+
if ($argument->isRequired() && (!$commandParser->hasArgument($key) || empty($commandParser->getArgumentValue($key)))) {
145145
throw new InvalidArgumentException(sprintf('Argument "%s" is required for command "%s".', $argument->getName(), $command->getName()));
146146
}
147147
if ($commandParser->hasArgument($key)) {
148-
$argv["--{$argument->getName()}"] = $commandParser->getArgumentValue($key);
148+
$argv["--{$key}"] = $commandParser->getArgumentValue($key);
149149
}else {
150-
$argv["--{$argument->getName()}"] = $argument->getDefaultValue();
150+
$argv["--{$key}"] = $argument->getDefaultValue();
151151
}
152152
}
153153

src/Input.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function getOptionValue(string $name)
4949
}
5050

5151
if (!$this->hasOption($name)) {
52-
throw new \InvalidArgumentException(sprintf('Option "%s" is not defined.', $name));
52+
return null;
5353
}
5454
return $this->options[$name];
5555
}

src/Option/CommandOption.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,29 @@ final class CommandOption
1010
private bool $isFlag;
1111

1212
public function __construct(
13-
string $name,
13+
string $name,
1414
?string $shortcut = null,
1515
?string $description = null,
16-
bool $isFlag = false
17-
) {
18-
$this->name = $name;
19-
$this->shortcut = $shortcut;
16+
bool $isFlag = false
17+
)
18+
{
19+
20+
if ($name === '') {
21+
throw new \InvalidArgumentException("Option name cannot be empty.");
22+
}
23+
24+
foreach (explode('-', $name) as $part) {
25+
if ($part === '' || !ctype_alpha($part)) {
26+
throw new \InvalidArgumentException("Option name must contain only letters and dashes. '$name' is invalid.");
27+
}
28+
}
29+
30+
if ($shortcut !== null && (strlen($shortcut) !== 1 || !ctype_alpha($shortcut))) {
31+
throw new \InvalidArgumentException('Shortcut must be a single character and contain only letters. "' . $shortcut . '" is invalid.');
32+
}
33+
34+
$this->name = strtolower($name);
35+
$this->shortcut = $shortcut !== null ? strtolower($shortcut) : null;
2036
$this->description = $description;
2137
$this->isFlag = $isFlag;
2238
}
@@ -40,4 +56,11 @@ public function isFlag(): bool
4056
{
4157
return $this->isFlag;
4258
}
59+
60+
public static function flag(string $name, ?string $shortcut = null, ?string $description = null): self {
61+
return new self($name, $shortcut, $description, true);
62+
}
63+
public static function withValue(string $name, ?string $shortcut = null, ?string $description = null): self {
64+
return new self($name, $shortcut, $description, false);
65+
}
4366
}

src/Output/ConsoleOutput.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ public function listKeyValues(array $items, bool $inlined = false): void
111111
}
112112

113113
foreach ($items as $key => $value) {
114+
$value = $this->variableToString($value);
115+
$value = implode(' ', explode(PHP_EOL, $value));
114116
$key = str_pad($key, $maxKeyLength, ' ', STR_PAD_RIGHT);
115117
$this->writeColor($key, 'green');
116118
$this->write(' : ');

0 commit comments

Comments
 (0)