Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
value meaning `return nothing` (@samdark)
- Chg #163: Rename `FilterableDataInterface::withFilterHandlers()` to `FilterableDataInterface::withAddedFilterHandlers()` (@samdark)
- Enh #190: Use `str_contains` for case-sensitive match in `LikeHandler` (@samdark)
- Bug #195: Fix invalid count in `IterableDataReader` when limit or/and offset used (@vjik)

## 1.0.1 January 25, 2023

Expand Down
42 changes: 25 additions & 17 deletions src/Reader/Iterable/IterableDataReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ final class IterableDataReader implements DataReaderInterface
/**
* @psalm-var array<string, IterableFilterHandlerInterface>
*/
private array $iterableFilterHandlers = [];
private array $iterableFilterHandlers;

/**
* @param iterable $data Data to iterate.
Expand Down Expand Up @@ -153,27 +153,48 @@ public function getSort(): ?Sort

public function count(): int
{
return count($this->read());
return count($this->internalRead(useLimitAndOffset: false));
}

/**
* @psalm-return array<TKey, TValue>
*/
public function read(): array
{
return $this->internalRead(useLimitAndOffset: true);
}

public function readOne(): array|object|null
{
if ($this->limit === 0) {
return null;
}

/** @infection-ignore-all Any value more than one in `withLimit()` will be ignored because returned `current()` */
return $this
->withLimit(1)
->getIterator()
->current();
}

/**
* @psalm-return array<TKey, TValue>
*/
private function internalRead(bool $useLimitAndOffset): array
{
$data = [];
$skipped = 0;
$sortedData = $this->sort === null ? $this->data : $this->sortItems($this->data, $this->sort);

foreach ($sortedData as $key => $item) {
// Don't return more than limit items.
if ($this->limit > 0 && count($data) === $this->limit) {
if ($useLimitAndOffset && $this->limit > 0 && count($data) === $this->limit) {
/** @infection-ignore-all Here continue === break */
break;
}

// Skip offset items.
if ($skipped < $this->offset) {
if ($useLimitAndOffset && $skipped < $this->offset) {
++$skipped;
continue;
}
Expand All @@ -187,19 +208,6 @@ public function read(): array
return $data;
}

public function readOne(): array|object|null
{
if ($this->limit === 0) {
return null;
}

/** @infection-ignore-all Any value more one in `withLimit()` will be ignored because returned `current()` */
return $this
->withLimit(1)
->getIterator()
->current();
}

/**
* Return whether an item matches iterable filter.
*
Expand Down
14 changes: 14 additions & 0 deletions tests/Reader/Iterable/IterableDataReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ public function testCounting(): void
$this->assertCount(5, $reader);
}

public function testCountWithLimit(): void
{
$reader = (new IterableDataReader(self::DEFAULT_DATASET))->withLimit(2);
$this->assertSame(5, $reader->count());
$this->assertCount(5, $reader);
}

public function testCountWithOffset(): void
{
$reader = (new IterableDataReader(self::DEFAULT_DATASET))->withOffset(3);
$this->assertSame(5, $reader->count());
$this->assertCount(5, $reader);
}

public function testReadOne(): void
{
$data = self::DEFAULT_DATASET;
Expand Down