diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f449dd9..874d1ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - laravel: [9, 10] + laravel: [10] steps: - uses: actions/checkout@v2 diff --git a/composer.json b/composer.json index 890e2a1..01ce6b7 100644 --- a/composer.json +++ b/composer.json @@ -23,10 +23,10 @@ "php": "^8.1" }, "require-dev": { - "orchestra/testbench": "^7.0|^8.0", - "nunomaduro/larastan": "^1.0|^2.4", - "pestphp/pest": "^1.2|^2.0", - "pestphp/pest-plugin-laravel": "^1.0|^2.0" + "orchestra/testbench": "^8.0", + "larastan/larastan": "^2.4", + "pestphp/pest": "^2.0", + "pestphp/pest-plugin-laravel": "^2.0" }, "minimum-stability": "dev", "prefer-stable": true, diff --git a/src/Comparable.php b/src/Comparable.php index d47de19..c655912 100644 --- a/src/Comparable.php +++ b/src/Comparable.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace ArchTech\Enums; +use Exception; +use Iterator; +use IteratorAggregate; + trait Comparable { public function is(mixed $enum): bool @@ -16,12 +20,30 @@ trait Comparable return ! $this->is($enum); } - public function in(array $enums): bool + public function in(array|object $enums): bool { - return [] !== array_filter($enums, fn (mixed $enum) => $this->is($enum)); + $iterator = $enums; + + if (! is_array($enums)) { + if ($enums instanceof Iterator) { + $iterator = $enums; + } elseif ($enums instanceof IteratorAggregate) { + $iterator = $enums->getIterator(); + } else { + throw new Exception('in() expects an iterable value'); + } + } + + foreach ($iterator as $item) { + if ($item === $this) { + return true; + } + } + + return false; } - public function notIn(array $enums): bool + public function notIn(array|object $enums): bool { return ! $this->in($enums); } diff --git a/tests/Pest/ComparableTest.php b/tests/Pest/ComparableTest.php index bebcf7c..11c980f 100644 --- a/tests/Pest/ComparableTest.php +++ b/tests/Pest/ComparableTest.php @@ -1,51 +1,44 @@ is(Status::PENDING)) - ->toBeTrue() - ->and(Status::PENDING->is(Status::DONE)) - ->toBeFalse() - ->and(Role::ADMIN->is(Role::ADMIN)) - ->toBeTrue() - ->and(Role::ADMIN->is(Role::GUEST)) - ->toBeFalse() - ->and(Role::ADMIN->is('admin')) - ->toBeFalse(); +test('the is method checks for equality', function () { + expect(Status::PENDING->is(Status::PENDING))->toBeTrue(); + expect(Status::PENDING->is(Status::DONE))->toBeFalse(); + expect(Role::ADMIN->is(Role::ADMIN))->toBeTrue(); + + expect(Role::ADMIN->is(Role::GUEST))->toBeFalse(); + expect(Role::ADMIN->is('admin'))->toBeFalse(); }); -it('compare not equal enum', function () { - expect(Status::PENDING->isNot(Status::DONE)) - ->toBeTrue() - ->and(Status::PENDING->isNot(Status::PENDING)) - ->toBeFalse() - ->and(Status::PENDING->isNot(Role::ADMIN)) - ->toBeTrue() - ->and(Role::ADMIN->isNot(Role::GUEST)) - ->toBeTrue() - ->and(Role::ADMIN->isNot(Role::ADMIN)) - ->toBeFalse() - ->and(Role::ADMIN->isNot('admin')) - ->toBeTrue(); +it('the isNot method checks for inequality', function () { + expect(Status::PENDING->isNot(Status::DONE))->toBeTrue(); + expect(Status::PENDING->isNot(Status::PENDING))->toBeFalse(); + expect(Status::PENDING->isNot(Role::ADMIN))->toBeTrue(); + expect(Role::ADMIN->isNot(Role::GUEST))->toBeTrue(); + + expect(Role::ADMIN->isNot(Role::ADMIN))->toBeFalse(); + expect(Role::ADMIN->isNot('admin'))->toBeTrue(); }); -it('compare in enums', function () { - expect(Status::PENDING->in([Status::PENDING, Status::DONE])) - ->toBeTrue() - ->and(Status::PENDING->in([Status::DONE])) - ->toBeFalse() - ->and(Status::PENDING->in([Role::ADMIN, Role::GUEST])) - ->toBeFalse() - ->and(Role::ADMIN->in([Role::ADMIN])) - ->toBeTrue(); +it('the in method checks for presence in an array', function () { + expect(Status::PENDING->in([Status::PENDING, Status::DONE]))->toBeTrue(); + expect(Role::ADMIN->in([Role::ADMIN]))->toBeTrue(); + + expect(Status::PENDING->in([Status::DONE]))->toBeFalse(); + expect(Status::PENDING->in([Role::ADMIN, Role::GUEST]))->toBeFalse(); }); -it('compare not in enums', function () { - expect(Status::PENDING->notIn([Status::DONE])) - ->toBeTrue() - ->and(Status::PENDING->notIn([Status::PENDING, Status::DONE])) - ->toBeFalse() - ->and(Role::ADMIN->notIn([Role::GUEST])) - ->toBeTrue() - ->and(Role::ADMIN->notIn([Role::ADMIN, Role::GUEST])) - ->toBeFalse(); +it('the not in method checks for absence in an array', function () { + expect(Status::PENDING->notIn([Status::DONE]))->toBeTrue(); + expect(Role::ADMIN->notIn([Role::GUEST]))->toBeTrue(); + + expect(Status::PENDING->notIn([Status::PENDING, Status::DONE]))->toBeFalse(); + expect(Role::ADMIN->notIn([Role::ADMIN, Role::GUEST]))->toBeFalse(); +}); + +test('the in and notIn methods work with Laravel collections', function () { + expect(Status::PENDING->in(collect([Status::PENDING, Status::DONE])))->toBeTrue(); + expect(Role::ADMIN->in(collect([Status::PENDING, Role::GUEST])))->toBeFalse(); + + expect(Status::DONE->notIn(collect([Status::PENDING])))->toBeTrue(); + expect(Role::ADMIN->notIn(collect([Role::ADMIN, Status::PENDING])))->toBeFalse(); });