OffsetPagination::urlGenerator()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Widget;
6
7
use Closure;
8
use Yiisoft\Data\Paginator\OffsetPaginator as Paginator;
9
use Yiisoft\Html\Html;
10
use Yiisoft\Yii\Bootstrap5\Widget;
11
12
class OffsetPagination extends Widget
13
{
14
    private array $options = [];
15
16
    private ?Closure $urlGenerator = null;
17
    private ?Paginator $paginator = null;
18
    private int $pagesCount;
19
    private int $currentPage;
20
    private array $pages;
21
    private bool $prepared;
22
23 2
    public function paginator(?Paginator $paginator): self
24
    {
25 2
        $this->paginator = $paginator;
26 2
        $this->prepared = false;
27 2
        return $this;
28
    }
29
30 2
    public function urlGenerator(Closure $generator): self
31
    {
32 2
        $this->urlGenerator = $generator;
33 2
        return $this;
34
    }
35
36 2
    public function isRequired(): bool
37
    {
38 2
        return $this->paginator === null ? false : $this->paginator->isRequired();
39
    }
40
41
    /**
42
     * The HTML attributes for the widget container tag. The following special options are recognized.
43
     *
44
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
45
     */
46
    public function options(array $value): self
47
    {
48
        $this->options = $value;
49
50
        return $this;
51
    }
52
53
    protected function run(): string
54
    {
55
        if ($this->paginator === null) {
56
            return '';
57
        }
58
        if (!isset($this->options['id'])) {
59
            $this->options['id'] = "{$this->getId()}-post-card";
60
        }
61
62
        $this->initOptions();
63
        $this->prepareButtons();
64
65
        return implode("\n", [
66
            Html::openTag('nav', $this->options),
67
            Html::openTag('ul', ['class' => 'pagination']),
68
            $this->renderButtons(),
69
            Html::closeTag('ul'),
70
            Html::closeTag('nav'),
71
        ]);
72
    }
73
74
    protected function prepareButtons(): void
75
    {
76
        if ($this->prepared) {
77
            return;
78
        }
79
        $this->pagesCount = $this->paginator->getTotalPages();
0 ignored issues
show
Bug introduced by
The method getTotalPages() 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

79
        /** @scrutinizer ignore-call */ 
80
        $this->pagesCount = $this->paginator->getTotalPages();

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...
80
        $this->currentPage = $this->paginator->getCurrentPage();
81
        if ($this->pagesCount > 9) {
82
            if ($this->currentPage <= 4) {
83
                $this->pages = [...range(1, 5), null, ...range($this->pagesCount - 2, $this->pagesCount)];
84
            } elseif ($this->pagesCount - $this->currentPage <= 4) {
85
                $this->pages = [1, 2, null, ...range($this->pagesCount - 5, $this->pagesCount)];
86
            } else {
87
                $this->pages = [
88
                    1,
89
                    2,
90
                    null,
91
                    $this->currentPage - 1,
92
                    $this->currentPage,
93
                    $this->currentPage + 1,
94
                    null,
95
                    $this->pagesCount - 1,
96
                    $this->pagesCount,
97
                ];
98
            }
99
        } else {
100
            $this->pages = range(1, $this->pagesCount);
101
        }
102
        $this->prepared = true;
103
    }
104
105
    protected function renderButtons(): string
106
    {
107
        $result = '';
108
109
        // `Previous` page
110
        $prevUrl = $this->paginator->isOnFirstPage() ? null : $this->getPageLink($this->currentPage - 1);
111
        $result .= Html::openTag('li', ['class' => $prevUrl === null ? 'page-item disabled' : 'page-item']);
112
        $result .= Html::a('Previous', $prevUrl, ['class' => 'page-link']);
113
        $result .= Html::closeTag('li');
114
115
        // Numeric buttons
116
        foreach ($this->pages as $page) {
117
            $isDisabled = $this->currentPage === $page || $page === null;
118
            $result .= Html::openTag('li', ['class' => $isDisabled ? 'page-item disabled' : 'page-item']);
119
            if ($page === null) {
120
                $result .= Html::span('…', ['class' => 'page-link']);
121
            } else {
122
                $result .= Html::a((string)$page, $this->getPageLink($page), ['class' => 'page-link']);
123
            }
124
            $result .= Html::closeTag('li');
125
        }
126
127
        // `Next` page
128
        $nextUrl = $this->paginator->isOnLastPage() ? null : $this->getPageLink($this->currentPage + 1);
129
        $result .= Html::openTag('li', ['class' => $nextUrl === null ? 'page-item disabled' : 'page-item']);
130
        $result .= Html::a('Next', $nextUrl, ['class' => 'page-link']);
131
        $result .= Html::closeTag('li');
132
133
        return $result;
134
    }
135
136
    protected function getPageLink(int $page): ?string
137
    {
138
        return $this->urlGenerator === null ? null : (string)($this->urlGenerator)($page);
139
    }
140
141
    protected function initOptions(): void
142
    {
143
        Html::addCssClass($this->options, [
144
            'aria-label' => 'Page navigation',
145
        ]);
146
    }
147
}
148