Skip to content

Commit

Permalink
[feature] allow invoke parameters to be optional
Browse files Browse the repository at this point in the history
  • Loading branch information
kbond committed Jan 9, 2021
1 parent ac6076b commit be1e2f7
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/Callback.php
Expand Up @@ -53,10 +53,16 @@ public function invoke(...$arguments)
continue;
}

if (!\array_key_exists($key, $parameters)) {
if (!\array_key_exists($key, $parameters) && !$argument->isOptional()) {
throw new \ArgumentCountError(\sprintf('No argument %d for callable. Expected type: "%s".', $key + 1, $argument->type()));
}

if ($argument->isOptional()) {
$arguments[$key] = null;

continue;
}

try {
$arguments[$key] = $argument->resolve($parameters[$key]);
} catch (UnresolveableArgument $e) {
Expand Down
20 changes: 20 additions & 0 deletions src/Callback/Parameter.php
Expand Up @@ -12,6 +12,9 @@
*/
abstract class Parameter
{
/** @var bool */
private $optional = false;

final public static function union(self ...$parameters): self
{
return new UnionParameter(...$parameters);
Expand All @@ -32,7 +35,16 @@ final public static function factory(callable $factory): ValueFactory
return new ValueFactory($factory);
}

final public function optional(): self
{
$this->optional = true;

return $this;
}

/**
* @internal
*
* @return mixed
*
* @throws UnresolveableArgument
Expand All @@ -54,6 +66,14 @@ final public function resolve(\ReflectionParameter $parameter)
return $value($type->getName());
}

/**
* @internal
*/
final public function isOptional(): bool
{
return $this->optional;
}

abstract public function type(): string;

abstract protected function valueFor(\ReflectionParameter $refParameter);
Expand Down
12 changes: 12 additions & 0 deletions tests/CallbackTest.php
Expand Up @@ -261,6 +261,18 @@ public function invoke_with_not_enough_required_arguments(): void
)
;
}

/**
* @test
*/
public function can_mark_invoke_parameter_arguments_as_optional(): void
{
$actual = Callback::createFor(static function() { return 'ret'; })
->invoke(Parameter::typed('string', 'foobar')->optional())
;

$this->assertSame('ret', $actual);
}
}

class Object1
Expand Down

0 comments on commit be1e2f7

Please sign in to comment.