Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rodber committed Jan 4, 2024
1 parent 918e48d commit f3c4bdf
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 28 deletions.
1 change: 0 additions & 1 deletion src/IterableParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public function __invoke(iterable $value): iterable
$strstr = substr($strstr, 2);
}
$calledIn = strpos($strstr, ', called in');

$message = $calledIn
? substr($strstr, 0, $calledIn)
: $strstr;
Expand Down
66 changes: 54 additions & 12 deletions src/UnionParameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,35 @@
use Chevere\Parameter\Interfaces\UnionParameterInterface;
use Chevere\Parameter\Traits\ArrayParameterTrait;
use Chevere\Parameter\Traits\ParameterAssertArrayTypeTrait;
use Chevere\Parameter\Traits\ParameterErrorMessageTrait;
use Chevere\Parameter\Traits\ParameterTrait;
use InvalidArgumentException;
use LogicException;
use Throwable;
use TypeError;
use function Chevere\Message\message;

final class UnionParameter implements UnionParameterInterface
{
use ParameterTrait;
use ArrayParameterTrait;
use ParameterAssertArrayTypeTrait;
use ParameterErrorMessageTrait;

Check failure on line 34 in src/UnionParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.1 test on ubuntu-latest

Class Chevere\Parameter\UnionParameter uses unknown trait Chevere\Parameter\Traits\ParameterErrorMessageTrait.

Check failure on line 34 in src/UnionParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.2 test on ubuntu-latest

Class Chevere\Parameter\UnionParameter uses unknown trait Chevere\Parameter\Traits\ParameterErrorMessageTrait.

Check failure on line 34 in src/UnionParameter.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 test on ubuntu-latest

Class Chevere\Parameter\UnionParameter uses unknown trait Chevere\Parameter\Traits\ParameterErrorMessageTrait.

/**
* @var array<mixed, mixed>|null
*/
private ?array $default = null;
private mixed $default = null;

final public function __construct(
private ParametersInterface $parameters,
private string $description = '',
) {
$this->type = $this->type();
if ($parameters->count() < 2) {
throw new LogicException(
(string) message(
'Must pass at least two parameters for union'
)
);
}

$this->parameters = $parameters;
}

Expand All @@ -50,23 +58,34 @@ public function __invoke(mixed $value): mixed
try {
return $parameter->__invoke($value);
} catch (Throwable $e) {
$type = $parameter::class;
$messages[] = <<<PLAIN
Parameter `{$name}` <{$type}>: {$e->getMessage()}
PLAIN;
$messages[] = $this->getParameterError($parameter, $name, $e);
}
}
$message = implode(';' . PHP_EOL, $messages);
$message = implode('; ', $messages);

throw new TypeError(
throw new InvalidArgumentException(
(string) message(
"Argument provided doesn't match union: %message%",
message: $message,
)
);
}

public function withAdded(ParameterInterface ...$parameter): static
public function withDefault(mixed $default): UnionParameterInterface
{
$this($default);
$new = clone $this;
$new->default = $default;

return $new;
}

public function default(): mixed
{
return $this->default;
}

public function withAdded(ParameterInterface ...$parameter): UnionParameterInterface
{
$new = clone $this;
foreach ($parameter as $name => $item) {
Expand All @@ -88,6 +107,29 @@ public function typeSchema(): string
return $this->type->primitive();
}

private function getParameterError(
ParameterInterface $parameter,
string $name,
Throwable $e
): string {
$type = $parameter::class;
$message = $e->getMessage();
$strstr = strstr($message, '::__invoke():', false);
if (! is_string($strstr)) {
$message = $message; // @codeCoverageIgnore
} else {
$message = substr($strstr, 14);
}
$calledIn = strpos($message, ', called in');
$message = $calledIn
? substr($message, 0, $calledIn)
: $message;

return <<<PLAIN
Parameter `{$name}` <{$type}>: {$message}
PLAIN;
}

private function typeName(): string
{
return TypeInterface::UNION;
Expand Down
83 changes: 68 additions & 15 deletions tests/UnionParameterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,77 @@
use Chevere\Parameter\Interfaces\TypeInterface;
use Chevere\Parameter\UnionParameter;
use InvalidArgumentException;
use LogicException;
use PHPUnit\Framework\TestCase;
use TypeError;
use function Chevere\Parameter\arguments;
use function Chevere\Parameter\float;
use function Chevere\Parameter\int;
use function Chevere\Parameter\null;
use function Chevere\Parameter\parameters;
use function Chevere\Parameter\string;
use function Chevere\Parameter\union;

final class UnionParameterTest extends TestCase
{
public function testConstructError(): void
{
$parameters = parameters(
foo: string(),
);
$this->expectException(LogicException::class);
$this->expectExceptionMessage('Must pass at least two parameters for union');
new UnionParameter($parameters);
}

public function testConstruct(): void
{
$parameter = new UnionParameter(
parameters()
$parameters = parameters(
foo: string(),
bar: int()
);
$parameter = new UnionParameter($parameters);
$this->assertSame(
TypeInterface::UNION,
$parameter->type()->primitive()
);
$this->assertCount(0, $parameter->parameters());
$this->assertCount(2, $parameter->parameters());
$this->assertSame(TypeInterface::UNION, $parameter->typeSchema());
$parameter('string');
$parameter(123);
}

public function testWithAdded(): void
{
$parameter = new UnionParameter(
parameters()
$foo = string();
$bar = int();
$baz = float();
$pun = null();
$parameters = parameters(
foo: $foo,
bar: $bar
);
$parameter = new UnionParameter($parameters);
$with = $parameter->withAdded(
baz: $baz,
pun: $pun
);
$one = string();
$two = int();
$with = $parameter->withAdded($one, $two);
$this->assertNotSame($parameter, $with);
$this->assertCount(2, $with->parameters());
$this->assertSame($one, $with->parameters()->get('0'));
$this->assertSame($two, $with->parameters()->get('1'));
$this->assertCount(4, $with->parameters());
$this->assertSame($foo, $with->parameters()->get('foo'));
$this->assertSame($bar, $with->parameters()->get('bar'));
$this->assertSame($baz, $with->parameters()->get('baz'));
$this->assertSame($pun, $with->parameters()->get('pun'));
}

public function testAssertCompatible(): void
{
$parameters = parameters(
string(),
int: int(),
string: string(),
);
$parametersAlt = parameters(
string(description: 'one'),
string: string(description: 'one'),
int: int(),
);
$parameter = new UnionParameter($parameters);
$compatible = new UnionParameter($parametersAlt);
Expand All @@ -71,9 +98,11 @@ public function testAssertNotCompatible(): void
{
$parameters = parameters(
string(),
int(),
);
$parametersAlt = parameters(
int(),
string(),
);
$parameter = new UnionParameter($parameters);
$compatible = new UnionParameter($parametersAlt);
Expand Down Expand Up @@ -104,7 +133,31 @@ public function testInvoke(): void
);
$parameter(10);
$parameter('10');
$this->expectException(TypeError::class);
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
<<<PLAIN
Argument provided doesn't match union: Parameter `0` <Chevere\Parameter\StringParameter>: Argument #1 (\$value) must be of type Stringable|string, float given; Parameter `1` <Chevere\Parameter\IntParameter>: Argument #1 (\$value) must be of type int, float given
PLAIN
);
$parameter(1.1);
}

public function testWithDefault(): void
{
$parameter = union(
string(),
int()
);
$this->assertSame(null, $parameter->default());
$with = $parameter->withDefault(10);
$this->assertNotSame($parameter, $with);
$this->assertSame(10, $with->default());
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
<<<PLAIN
Argument provided doesn't match union: Parameter `0` <Chevere\Parameter\StringParameter>: Argument #1 (\$value) must be of type Stringable|string, array given; Parameter `1` <Chevere\Parameter\IntParameter>: Argument #1 (\$value) must be of type int, array given
PLAIN
);
$parameter->withDefault([]);
}
}

0 comments on commit f3c4bdf

Please sign in to comment.