From 7ceec460026ddcfba8d21925ae5475e4bef4ce9a Mon Sep 17 00:00:00 2001 From: Ben Roberts Date: Sat, 6 Jan 2024 18:02:10 +0100 Subject: [PATCH] Add firstOrFail() and lastOrFail() methods --- src/AbstractImmutableCollection.php | 17 ++++++++++ src/Exception/ItemNotFoundException.php | 9 ++++++ tests/unit/CollectionTest.php | 41 +++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/Exception/ItemNotFoundException.php diff --git a/src/AbstractImmutableCollection.php b/src/AbstractImmutableCollection.php index a7f7dcb..19195d3 100644 --- a/src/AbstractImmutableCollection.php +++ b/src/AbstractImmutableCollection.php @@ -6,6 +6,7 @@ use ArrayIterator; use Headsnet\Collections\Exception\ImmutabilityException; use Headsnet\Collections\Exception\InvalidTypeException; +use Headsnet\Collections\Exception\ItemNotFoundException; use Headsnet\Collections\Exception\OutOfRangeException; /** @@ -77,6 +78,14 @@ public function first() return reset($this->items) ?: null; } + /** + * @return TValue + */ + public function firstOrFail() + { + return reset($this->items) ?: throw new ItemNotFoundException(); + } + /** * @return TValue|null */ @@ -85,6 +94,14 @@ public function last() return end($this->items) ?: null; } + /** + * @return TValue + */ + public function lastOrFail() + { + return end($this->items) ?: throw new ItemNotFoundException(); + } + /** * @param AbstractImmutableCollection $compareWith */ diff --git a/src/Exception/ItemNotFoundException.php b/src/Exception/ItemNotFoundException.php new file mode 100644 index 0000000..e1da963 --- /dev/null +++ b/src/Exception/ItemNotFoundException.php @@ -0,0 +1,9 @@ +assertNull($sut->first()); } + public function test_first_or_fail_returns_first_item(): void + { + $collectionItem1 = new DummyCollectionItem(); + $collectionItem2 = new DummyCollectionItem(); + $collectionItem3 = new DummyCollectionItem(); + + $sut = new DummyCollection([$collectionItem1, $collectionItem2, $collectionItem3]); + + $this->assertSame($collectionItem1, $sut->firstOrFail()); + } + + public function test_first_or_fail_throws_exception_if_collection_is_empty(): void + { + $sut = new DummyCollection([]); + + $this->expectException(ItemNotFoundException::class); + + $sut->firstOrFail(); + } + public function test_last_returns_last_item(): void { $collectionItem1 = new DummyCollectionItem(); @@ -78,6 +99,26 @@ public function test_last_returns_null_if_collection_is_empty(): void $this->assertNull($sut->last()); } + public function test_last_or_fail_returns_first_item(): void + { + $collectionItem1 = new DummyCollectionItem(); + $collectionItem2 = new DummyCollectionItem(); + $collectionItem3 = new DummyCollectionItem(); + + $sut = new DummyCollection([$collectionItem1, $collectionItem2, $collectionItem3]); + + $this->assertSame($collectionItem3, $sut->lastOrFail()); + } + + public function test_last_or_fail_throws_exception_if_collection_is_empty(): void + { + $sut = new DummyCollection([]); + + $this->expectException(ItemNotFoundException::class); + + $sut->lastOrFail(); + } + public function test_equality_check_succeeds_correctly(): void { $collectionItem1 = new DummyCollectionItem();