Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add paging functionality to ResultSet #136

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
81 changes: 70 additions & 11 deletions src/ResultSet.php
Original file line number Diff line number Diff line change
@@ -1,63 +1,86 @@
<?php

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Class ipl\\Orm\\ResultSet implements generic interface Iterator but does not specify its types\: TKey, TValue$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$limit with no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:advance\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasMore\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasResult\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$cache has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.1 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$generator has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Class ipl\\Orm\\ResultSet implements generic interface Iterator but does not specify its types\: TKey, TValue$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$limit with no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:advance\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasMore\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasResult\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$cache has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.0 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$generator has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Class ipl\\Orm\\ResultSet implements generic interface Iterator but does not specify its types\: TKey, TValue$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$limit with no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:advance\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasMore\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasResult\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$cache has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.2 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$generator has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Class ipl\\Orm\\ResultSet implements generic interface Iterator but does not specify its types\: TKey, TValue$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$limit with no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:__construct\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:advance\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasMore\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:hasResult\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has no return type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Method ipl\\Orm\\ResultSet\:\:yieldTraversable\(\) has parameter \$traversable with no value type specified in iterable type Traversable\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$cache has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

Check failure on line 1 in src/ResultSet.php

View workflow job for this annotation

GitHub Actions / phpstan / Static analysis with phpstan and php 8.3 on ubuntu-latest

Ignored error pattern #^Property ipl\\Orm\\ResultSet\:\:\$generator has no type specified\.$# in path /home/runner/work/ipl-orm/ipl-orm/src/ResultSet.php was not matched in reported errors.

namespace ipl\Orm;

use ArrayIterator;
use BadMethodCallException;
use Generator;
use Iterator;
use Traversable;

/**
* Dataset containing database rows
*
* @implements Iterator<int, mixed>
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
*/
class ResultSet implements Iterator
{
/** @var ArrayIterator<int, mixed> */
protected $cache;

/** @var bool Whether cache is disabled */
protected $isCacheDisabled = false;

/** @var Generator<int, mixed, mixed, mixed> */
protected $generator;

/** @var ?int */
protected $limit;

/** @var ?int */
protected $position;

public function __construct(Traversable $traversable, $limit = null)
/** @var ?int */
protected $offset;

/** @var ?int */
protected $pageSize;

/**
* @param Traversable<int, mixed> $traversable
* @param ?int $limit
* @param ?int $offset
*/
public function __construct(Traversable $traversable, ?int $limit = null, ?int $offset = null)
{
$this->cache = new ArrayIterator();
$this->generator = $this->yieldTraversable($traversable);
$this->limit = $limit;
$this->offset = $offset;
}

/**
* Create a new result set from the given query
*
* @param Query $query
*
* @return static
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
* @return ResultSet
*/
public static function fromQuery(Query $query)
public static function fromQuery(Query $query): ResultSet
{
return new static($query->yieldResults(), $query->getLimit());
return new static($query->yieldResults(), $query->getLimit(), $query->getOffset());
}

/**
* Do not cache query result
*
* ResultSet instance can only be iterated once
*
* @return $this
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
* @return ResultSet
*/
public function disableCache()
public function disableCache(): ResultSet
{
$this->isCacheDisabled = true;

return $this;
}

public function hasMore()
public function hasMore(): bool
{
return $this->generator->valid();
}

public function hasResult()
public function hasResult(): bool
{
return $this->generator->valid();
}
Expand Down Expand Up @@ -86,7 +109,7 @@
}
}

public function key(): int
public function key(): ?int
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
{
if ($this->position === null) {
$this->advance();
Expand Down Expand Up @@ -117,7 +140,7 @@
}
}

protected function advance()
protected function advance(): void
{
if (! $this->generator->valid()) {
return;
Expand All @@ -137,10 +160,46 @@
}
}

protected function yieldTraversable(Traversable $traversable)
/**
* @param Traversable<int, mixed> $traversable
* @return Generator
*/
protected function yieldTraversable(Traversable $traversable): Generator
{
foreach ($traversable as $key => $value) {
yield $key => $value;
}
}

/**
* Sets the amount of items a page should contain (only needed for pagination)
*
* @param ?int $size
* @return void
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
*/
public function setPageSize(?int $size): void
{
$this->pageSize = $size;
}

/**
* Returns the current page calculated from the {@see ResultSet::$offset} and the {@see ResultSet::$pageSize}
*
* @return int
* @throws BadMethodCallException if no {@see ResultSet::$pageSize} has been provided
*/
protected function getCurrentPage(): int
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
{
if ($this->pageSize) {
if ($this->offset && $this->offset > $this->pageSize) {
// offset is not on the first page anymore
return intval(floor($this->offset / $this->pageSize));
}

// no offset defined or still on page 1
return 1;
}

throw new BadMethodCallException(`The 'pageSize' property has not been set. Cannot calculate pages.`);
ncosta-ic marked this conversation as resolved.
Show resolved Hide resolved
}
}
Loading