Passed
Pull Request — master (#24)
by
unknown
02:14
created

OffsetPaginator::withNextPageToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 1
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Yiisoft\Data\Paginator;
5
6
use Yiisoft\Data\Reader\CountableDataInterface;
7
use Yiisoft\Data\Reader\DataReaderInterface;
8
use Yiisoft\Data\Reader\OffsetableDataInterface;
9
10
/**
11
 * OffsetPaginator
12
 */
13
final class OffsetPaginator implements PaginatorInterface
14
{
15
    /**
16
     * @var OffsetableDataInterface|DataReaderInterface|CountableDataInterface
17
     */
18
    private $dataReader;
19
20
    private $currentPage = 1;
21
    private $pageSize = self::DEFAULT_PAGE_SIZE;
22
23
    /**
24
     * @var array|null Reader cache against repeated scans.
25
     *
26
     * @see initializeInternal()
27
     */
28
    private $readCache;
29
    /**
30
     * @var int|null Total count cache against repeated scans.
31
     *
32
     * See more {@see initializeInternal()}.
33
     */
34
    private $totalCountCache;
35
36 11
    public function __construct(DataReaderInterface $dataReader)
37
    {
38 11
        if (!$dataReader instanceof OffsetableDataInterface) {
39 1
            throw new \InvalidArgumentException('Data reader should implement OffsetableDataInterface in order to be used with offset paginator');
40
        }
41
42 10
        if (!$dataReader instanceof CountableDataInterface) {
43
            throw new \InvalidArgumentException('Data reader should implement CountableDataInterface in order to be used with offset paginator');
44
        }
45
46 10
        $this->dataReader = $dataReader;
47 10
    }
48
49
    public function getCurrentPage(): int
50
    {
51
        return $this->currentPage;
52
    }
53
54 8
    public function withCurrentPage(int $page)
55
    {
56 8
        if ($page < 1) {
57 1
            throw new \InvalidArgumentException('Current page should be at least 1');
58
        }
59
60 7
        $new = clone $this;
61 7
        $new->currentPage = $page;
62 7
        return $new;
63
    }
64
65 9
    public function withPageSize(int $size)
66
    {
67 9
        if ($size < 1) {
68 1
            throw new \InvalidArgumentException('Page size should be at least 1');
69
        }
70
71 8
        $new = clone $this;
72 8
        $new->pageSize = $size;
73 8
        return $new;
74
    }
75
76 2
    public function isOnFirstPage(): bool
77
    {
78 2
        return $this->currentPage === 1;
79
    }
80
81 2
    public function isOnLastPage(): bool
82
    {
83 2
        return $this->currentPage === $this->getTotalPages();
84
    }
85
86 3
    public function getTotalPages(): int
87
    {
88 3
        $totalCount = $this->totalCountCache;
89 3
        if($totalCount === null) {
90 3
            $totalCount = $this->dataReader->count();
0 ignored issues
show
Bug introduced by
The method count() does not exist on Yiisoft\Data\Reader\DataReaderInterface. It seems like you code against a sub-type of Yiisoft\Data\Reader\DataReaderInterface such as Yiisoft\Data\Reader\IterableDataReader. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

90
            /** @scrutinizer ignore-call */ 
91
            $totalCount = $this->dataReader->count();
Loading history...
Bug introduced by
The method count() does not exist on Yiisoft\Data\Reader\OffsetableDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Data\Reader\OffsetableDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

90
            /** @scrutinizer ignore-call */ 
91
            $totalCount = $this->dataReader->count();
Loading history...
91
        }
92 3
        return (int) ceil($totalCount / $this->pageSize);
93
    }
94
95 3
    private function getOffset(): int
96
    {
97 3
        return $this->pageSize * ($this->currentPage - 1);
98
    }
99
100 3
    public function read(): iterable
101
    {
102 3
        if($this->readCache !== null) {
103
            return $this->readCache;
104
        }
105 3
        $reader = $this->dataReader->withLimit($this->pageSize)->withOffset($this->getOffset());
0 ignored issues
show
Bug introduced by
The method withOffset() does not exist on Yiisoft\Data\Reader\DataReaderInterface. It seems like you code against a sub-type of Yiisoft\Data\Reader\DataReaderInterface such as Yiisoft\Data\Reader\IterableDataReader. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $reader = $this->dataReader->withLimit($this->pageSize)->/** @scrutinizer ignore-call */ withOffset($this->getOffset());
Loading history...
Bug introduced by
The method withOffset() does not exist on Yiisoft\Data\Reader\CountableDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Data\Reader\CountableDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $reader = $this->dataReader->withLimit($this->pageSize)->/** @scrutinizer ignore-call */ withOffset($this->getOffset());
Loading history...
Bug introduced by
The method withLimit() does not exist on Yiisoft\Data\Reader\OffsetableDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Data\Reader\OffsetableDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $reader = $this->dataReader->/** @scrutinizer ignore-call */ withLimit($this->pageSize)->withOffset($this->getOffset());
Loading history...
Bug introduced by
The method withLimit() does not exist on Yiisoft\Data\Reader\CountableDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Data\Reader\CountableDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

105
        $reader = $this->dataReader->/** @scrutinizer ignore-call */ withLimit($this->pageSize)->withOffset($this->getOffset());
Loading history...
106 3
        yield from $reader->read();
0 ignored issues
show
Bug introduced by
The method read() does not exist on Yiisoft\Data\Reader\OffsetableDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Data\Reader\OffsetableDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

106
        yield from $reader->/** @scrutinizer ignore-call */ read();
Loading history...
Bug introduced by
The method read() does not exist on Yiisoft\Data\Reader\CountableDataInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Yiisoft\Data\Reader\CountableDataInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

106
        yield from $reader->/** @scrutinizer ignore-call */ read();
Loading history...
107 3
    }
108
109
    public function getNextPageToken(): ?string
110
    {
111
        return $this->isOnLastPage() ? null : (string) ($this->currentPage + 1);
112
    }
113
114
    public function getPreviousPageToken(): ?string
115
    {
116
        return $this->isOnFirstPage() ? null : (string) ($this->currentPage - 1);
117
    }
118
119
    public function withNextPageToken(?string $token)
120
    {
121
        return $this->withCurrentPage(intval($token));
122
    }
123
124
    public function withPreviousPageToken(?string $token)
125
    {
126
        return $this->withCurrentPage(intval($token));
127
    }
128
129
    public function getCurrentPageSize(): int
130
    {
131
        $this->initializeInternal();
132
        return count($this->readCache);
133
    }
134
135 8
    public function __clone()
136
    {
137 8
        $this->readCache = null;
138 8
        $this->totalCountCache = null;
139 8
    }
140
141
    protected function initializeInternal(): void
142
    {
143
        if($this->readCache !== null) {
144
            return;
145
        }
146
        $cache = [];
147
        foreach ($this->read() as $value) {
148
            $cache[] = $value;
149
        }
150
        $this->readCache = $cache;
151
    }
152
}
153