Passed
Pull Request — master (#49)
by Alexander
25:24 queued 10:30
created

CycleDataPaginator::isOnLastPage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace App;
4
5
use Closure;
6
use Countable;
7
use Cycle\ORM\Select;
8
use Spiral\Database\Query\QueryInterface;
9
use Spiral\Pagination\PaginableInterface;
10
11
class CycleDataPaginator implements DataPaginatorInterface
12
{
13
    private int $count;
14
    private int $pagesCount = 1;
15
    private int $limit;
16
    private int $currentPage = 1;
17
    private array $pageTokens = [];
18
    private ?Closure $tokenGenerator = null;
19
    private object $dataQuery;
20
    private ?iterable $dataCache = null;
21
22
    /**
23
     * CycleDataPaginator constructor.
24
     * @param Select|QueryInterface $query
25
     * @param int $limit
26
     * @param int $count
27
     */
28
    public function __construct($query, int $limit = 25, int $count = 0)
29
    {
30
        $this->dataQuery = $query;
31
        if ($count > 0) {
32
            $this->count = $count;
33
        } elseif ($query instanceof Countable) {
34
            $this->count = $query->count();
35
        }
36
        $this->limit = max($limit, 1);
37
        $this->calcPages();
38
    }
39
    public function __clone()
40
    {
41
        $this->dataCache = null;
42
    }
43
44
    public function read(): iterable
45
    {
46
        if ($this->dataCache !== null) {
47
            return $this->dataCache;
48
        }
49
        $this->paginate();
50
        return $this->dataCache = $this->dataQuery->fetchAll();
51
    }
52
    public function getCurrentPageSize(): int
53
    {
54
        if ($this->dataCache instanceof Countable) {
55
            return $this->dataCache->count();
0 ignored issues
show
Bug introduced by
The method count() does not exist on null. ( Ignorable by Annotation )

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

55
            return $this->dataCache->/** @scrutinizer ignore-call */ count();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
56
        }
57
        if ($this->pagesCount === 1) {
58
            return $this->count;
59
        }
60
        if ($this->currentPage === $this->pagesCount) {
61
            return $this->count - ($this->currentPage - 1) * $this->limit;
62
        }
63
        return $this->limit;
64
    }
65
    public function getItemsCount(): int
66
    {
67
        return $this->count;
68
    }
69
    public function withTokenGenerator(?Closure $closure): self
70
    {
71
        $paginator = clone $this;
72
        $paginator->tokenGenerator = $closure;
73
        return $paginator;
74
    }
75
    public function isOnLastPage(): bool
76
    {
77
        return $this->currentPage === $this->pagesCount;
78
    }
79
    public function isOnFirstPage(): bool
80
    {
81
        return $this->currentPage === 1;
82
    }
83
    public function getPageToken(int $page): ?string
84
    {
85
        if ($page < 1 || $page > $this->pagesCount) {
86
            return null;
87
        }
88
        if (isset($this->pageTokens[$this->limit][$page])) {
89
            return $this->pageTokens[$this->limit][$page];
90
        }
91
        return $this->tokenGenerator === null ? null : ($this->tokenGenerator)($page);
92
    }
93
    public function withPreviousPageToken(?string $token): self
94
    {
95
        $paginator = clone $this;
96
        $paginator->pageTokens[$paginator->limit][$paginator->currentPage - 1] = $token;
97
        return $paginator;
98
    }
99
    public function withNextPageToken(?string $token): self
100
    {
101
        $paginator = clone $this;
102
        $paginator->pageTokens[$paginator->limit][$paginator->currentPage + 1] = $token;
103
        return $paginator;
104
    }
105
    public function getPreviousPageToken(): ?string
106
    {
107
        return $this->getPageToken($this->currentPage - 1);
108
    }
109
    public function getNextPageToken(): ?string
110
    {
111
        return $this->getPageToken($this->currentPage + 1);
112
    }
113
    public function withCurrentPage(int $num): self
114
    {
115
        $paginator = clone $this;
116
        $paginator->currentPage = max(1, min($num, $this->pagesCount));
117
        return $paginator;
118
    }
119
    public function withPageSize(int $limit): self
120
    {
121
        $paginator = clone $this;
122
        $paginator->limit = max($limit, 1);
123
        $paginator->calcPages();
124
        return $paginator;
125
    }
126
    public function getPageSize(): int
127
    {
128
        return $this->limit;
129
    }
130
    public function getCurrentPage(): int
131
    {
132
        return $this->currentPage;
133
    }
134
    public function getTotalPages(): int
135
    {
136
        return $this->pagesCount;
137
    }
138
    public function getOffset(): int
139
    {
140
        return ($this->currentPage - 1) * $this->limit;
141
    }
142
143
    private function calcPages(): self
144
    {
145
        $this->pagesCount = $this->count > 0
146
            ? (int)ceil($this->count / $this->limit)
147
            : $this->pagesCount = 1;
148
        return $this;
149
    }
150
    private function paginate(): self
151
    {
152
        $this->dataQuery = clone $this->dataQuery;
153
        $offset = $this->getOffset();
154
        if ($this->dataQuery instanceof PaginableInterface) {
155
            $this->dataQuery->limit($this->limit);
156
            $this->dataQuery->offset($offset);
157
        }
158
        return $this;
159
    }
160
}
161