Skip to content

Commit

Permalink
Remove duplicate code. (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
terabytesoftw committed May 5, 2023
1 parent e81368d commit 5a9de9c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 120 deletions.
55 changes: 55 additions & 0 deletions src/AbstractIteratorProvider.php
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Yii\DataProvider;

use ArrayIterator;
use Traversable;

abstract class AbstractIteratorProvider implements IteratorProviderInterface
{
protected int $limit = self::DEFAULT_LIMIT;
protected int $offset = self::DEFAULT_OFFSET;

public function getIterator(): Traversable
{
return new ArrayIterator($this->read());
}

public function getLimit(): int
{
return $this->limit;
}

public function getOffset(): int
{
return $this->offset;
}

public function withLimit(int $value): static
{
// validate limit
if ($value < 0) {
$value = self::DEFAULT_LIMIT;
}

$new = clone $this;
$new->limit = $value;

return $new;
}

public function withOffset(int $value): static
{
$new = clone $this;
$new->offset = $value;

// validate offset
if ($new->limit * ($new->offset - 1) <= 0) {
$new->offset = self::DEFAULT_OFFSET;
}

return $new;
}
}
42 changes: 2 additions & 40 deletions src/ActiveIteratorProvider.php
Expand Up @@ -4,18 +4,13 @@

namespace Yii\DataProvider;

use ArrayIterator;
use Traversable;
use Yiisoft\ActiveRecord\ActiveQueryInterface;

/**
* Provides a way to iterate over the results of an Active Query with support for pagination.
*/
final class ActiveIteratorProvider implements IteratorProviderInterface
final class ActiveIteratorProvider extends AbstractIteratorProvider
{
private int $limit = self::DEFAULT_LIMIT;
private int $offset = self::DEFAULT_OFFSET;

public function __construct(private ActiveQueryInterface $activeQuery)
{
}
Expand All @@ -25,46 +20,13 @@ public function count(): int
return (int) $this->activeQuery->count();
}

public function getIterator(): Traversable
{
return new ArrayIterator($this->read());
}

public function getLimit(): int
{
return $this->limit;
}

public function getOffset(): int
{
return $this->offset;
}

public function read(): array
{
$offset = $this->offset >= 1 ? $this->limit * ($this->offset - 1) : $this->offset;

return $this->activeQuery->limit($this->limit)->offset($offset)->all();
return $this->activeQuery->limit($this->limit)->offset($this->offset)->all();
}

public function readOne(): array
{
return $this->activeQuery->limit(1)->offset($this->offset)->all();
}

public function withLimit(int $value): static
{
$new = clone $this;
$new->limit = $value;

return $new;
}

public function withOffset(int $value): static
{
$new = clone $this;
$new->offset = $value;

return $new;
}
}
43 changes: 2 additions & 41 deletions src/ArrayIteratorProvider.php
Expand Up @@ -4,20 +4,14 @@

namespace Yii\DataProvider;

use ArrayIterator;
use Traversable;

use function array_slice;
use function count;

/**
* Provides a way to iterate over an array with support for pagination.
*/
final class ArrayIteratorProvider implements IteratorProviderInterface
final class ArrayIteratorProvider extends AbstractIteratorProvider
{
private int $limit = self::DEFAULT_LIMIT;
private int $offset = self::DEFAULT_OFFSET;

public function __construct(private array $data)
{
}
Expand All @@ -27,46 +21,13 @@ public function count(): int
return count($this->data);
}

public function getIterator(): Traversable
{
return new ArrayIterator($this->read());
}

public function getLimit(): int
{
return $this->limit;
}

public function getOffset(): int
{
return $this->offset;
}

public function read(): array
{
$offset = $this->offset >= 1 ? $this->limit * ($this->offset - 1) : $this->offset;

return array_slice($this->data, $offset, $this->limit);
return array_slice($this->data, $this->offset, $this->limit);
}

public function readOne(): array
{
return array_slice($this->data, $this->offset, 1);
}

public function withLimit(int $value): static
{
$new = clone $this;
$new->limit = $value;

return $new;
}

public function withOffset(int $value): static
{
$new = clone $this;
$new->offset = $value;

return $new;
}
}
41 changes: 2 additions & 39 deletions src/SqlIteratorDataProvider.php
Expand Up @@ -4,20 +4,15 @@

namespace Yii\DataProvider;

use ArrayIterator;
use Traversable;
use Yiisoft\Db\Connection\ConnectionInterface;

use function count;

/**
* Provides a way to iterate over the results of a SQL query with support for pagination.
*/
final class SqlIteratorDataProvider implements IteratorProviderInterface
final class SqlIteratorDataProvider extends AbstractIteratorProvider
{
private int $limit = self::DEFAULT_LIMIT;
private int $offset = self::DEFAULT_OFFSET;

public function __construct(private ConnectionInterface $db, private string $sql, private array $params = [])
{
}
Expand All @@ -27,25 +22,9 @@ public function count(): int
return count($this->read());
}

public function getIterator(): Traversable
{
return new ArrayIterator($this->read());
}

public function getLimit(): int
{
return $this->limit;
}

public function getOffset(): int
{
return $this->offset;
}

public function read(): array
{
$offset = $this->offset >= 1 ? $this->limit * ($this->offset - 1) : $this->offset;
$sql = $this->db->getQueryBuilder()->buildOrderByAndLimit($this->sql, [], $this->limit, $offset);
$sql = $this->db->getQueryBuilder()->buildOrderByAndLimit($this->sql, [], $this->limit, $this->offset);

return $this->db->createCommand($sql, $this->params)->queryAll();
}
Expand All @@ -54,20 +33,4 @@ public function readOne(): array
{
return $this->withLimit(1)->read();
}

public function withLimit(int $value): static
{
$new = clone $this;
$new->limit = $value;

return $new;
}

public function withOffset(int $value): static
{
$new = clone $this;
$new->offset = $value;

return $new;
}
}
28 changes: 28 additions & 0 deletions tests/Base/AbstractActiveIteratorDataProviderTest.php
Expand Up @@ -118,6 +118,34 @@ public function testReadOne(): void
);
}

public function testWithLimitWithNegative(): void
{
$userQuery = new ActiveQuery(User::class, $this->db);
$activeIteratorProvider = (new ActiveIteratorProvider($userQuery))->withLimit(-1)->withOffset(1)->read();

$this->assertCount(3, $activeIteratorProvider);
$this->assertSame(
['id' => 1, 'username' => 'admin', 'email' => 'admin@example.com'],
$activeIteratorProvider[0]->getAttributes(),
);
$this->assertSame(
['id' => 2, 'username' => 'user', 'email' => 'user@example.com'],
$activeIteratorProvider[1]->getAttributes(),
);
$this->assertSame(
['id' => 3, 'username' => 'guest', 'email' => 'guest@example.com'],
$activeIteratorProvider[2]->getAttributes(),
);
}

public function testWithLimitWithZero(): void
{
$userQuery = new ActiveQuery(User::class, $this->db);
$activeIteratorProvider = (new ActiveIteratorProvider($userQuery))->withLimit(0)->withOffset(1)->read();

$this->assertCount(0, $activeIteratorProvider);
}

public function testWithOffset(): void
{
$userQuery = new ActiveQuery(User::class, $this->db);
Expand Down

0 comments on commit 5a9de9c

Please sign in to comment.