Skip to content

Commit

Permalink
Merge pull request #25 from petrknap/improved-or-else-throw-method
Browse files Browse the repository at this point in the history
Added support for exception class name instead of supplier
  • Loading branch information
petrknap authored Jun 25, 2024
2 parents 55222f4 + 6ea5785 commit ad2d535
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 9 deletions.
25 changes: 23 additions & 2 deletions src/Optional.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,32 @@ public function orElseGet(callable $otherSupplier): mixed
return static::isSupported($other) ? $other : throw new InvalidArgumentException('Other supplier must return supported other.');
}

public function orElseThrow(?callable $exceptionSupplier = null): mixed
/**
* @template E of Throwable
*
* @param null|class-string<E>|callable(): E $exceptionSupplier
*
* @return T
*
* @throws E
*/
public function orElseThrow(null|string|callable $exceptionSupplier = null): mixed
{
if ($exceptionSupplier === null) {
return $this->orElseThrow(static fn () => new Exception\CouldNotGetValueOfEmptyOptional());
}

if (is_string($exceptionSupplier)) {
/** @var class-string<E> $exceptionSupplier */
if (!class_exists($exceptionSupplier, autoload: true)) {
throw new InvalidArgumentException('Exception supplier must be existing class name.');
}
return $this->orElseThrow(static fn () => new $exceptionSupplier());
}

return $this->orElseGet(static function () use ($exceptionSupplier): never {
/** @var Throwable|mixed $exception */
$exception = $exceptionSupplier === null ? new Exception\CouldNotGetValueOfEmptyOptional() : $exceptionSupplier();
$exception = $exceptionSupplier();
if ($exception instanceof Throwable) {
throw $exception;
}
Expand Down
28 changes: 21 additions & 7 deletions tests/OptionalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace PetrKnap\Optional;

use Exception as SomeException;
use DomainException as SomeException;
use LogicException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -213,20 +213,34 @@ public static function dataMethodOrElseGetWorks(): array
}

#[DataProvider('dataMethodOrElseThrowWorks')]
public function testMethodOrElseThrowWorks(Optional $optional, ?string $expectedValue, ?string $expectedException): void
public function testMethodOrElseThrowWorks(Optional $optional, null|string|callable $exceptionProvider, ?string $expectedValue, ?string $expectedException): void
{
if ($expectedException) {
self::expectException($expectedException);
}
self::assertSame($expectedValue, $optional->orElseThrow(static fn(): SomeException => new SomeException()));
self::assertSame($expectedValue, $optional->orElseThrow($exceptionProvider));
}

public static function dataMethodOrElseThrowWorks(): array
public static function dataMethodOrElseThrowWorks(): iterable
{
return self::makeDataSet([
[self::VALUE, null],
[null, SomeException::class],
$dataSet = self::makeDataSet([
[null, self::VALUE, null],
[null, null, SomeException::class],
]);
foreach ($dataSet as $name => $data) {
$data[3] = $data[3] === null ? null : Exception\CouldNotGetValueOfEmptyOptional::class;
yield "{$name} + null supplier" => $data;
}
$exceptionSupplier = static fn(): SomeException => new SomeException();
foreach ($dataSet as $name => $data) {
$data[1] = $exceptionSupplier;
yield "{$name} + callable supplier" => $data;
}
$exceptionSupplier = SomeException::class;
foreach ($dataSet as $name => $data) {
$data[1] = $exceptionSupplier;
yield "{$name} + string supplier" => $data;
}
}

private static function makeDataSet(array $args): array
Expand Down

0 comments on commit ad2d535

Please sign in to comment.