Passed
Pull Request — master (#566)
by Rustam
03:47 queued 02:18
created

OffsetPagination   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 70
dl 0
loc 135
rs 10
c 0
b 0
f 0
wmc 25

9 Methods

Rating   Name   Duplication   Size   Complexity  
A isRequired() 0 3 2
A initOptions() 0 4 1
A getPageLink() 0 3 2
A options() 0 5 1
B renderButtons() 0 29 9
A urlGenerator() 0 5 1
A prepareButtons() 0 29 5
A paginator() 0 6 1
A render() 0 18 3
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;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Data\Paginator\OffsetPaginator was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Yiisoft\Html\Html;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Html\Html was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Yiisoft\Yii\Bootstrap5\Widget;
0 ignored issues
show
Bug introduced by
The type Yiisoft\Yii\Bootstrap5\Widget was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
12
final 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
    public function paginator(?Paginator $paginator): self
24
    {
25
        $this->paginator = $paginator;
26
        $this->prepared = false;
27
28
        return $this;
29
    }
30
31
    public function urlGenerator(Closure $generator): self
32
    {
33
        $this->urlGenerator = $generator;
34
35
        return $this;
36
    }
37
38
    public function isRequired(): bool
39
    {
40
        return $this->paginator === null ? false : $this->paginator->isRequired();
41
    }
42
43
    /**
44
     * The HTML attributes for the widget container tag. The following special options are recognized.
45
     *
46
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
47
     */
48
    public function options(array $value): self
49
    {
50
        $this->options = $value;
51
52
        return $this;
53
    }
54
55
    public function render(): string
56
    {
57
        if ($this->paginator === null) {
58
            return '';
59
        }
60
        if (!isset($this->options['id'])) {
61
            $this->options['id'] = "{$this->getId()}-post-card";
62
        }
63
64
        $this->initOptions();
65
        $this->prepareButtons();
66
67
        return implode("\n", [
68
            Html::openTag('nav', $this->options),
69
            Html::openTag('ul', ['class' => 'pagination']),
70
            $this->renderButtons(),
71
            Html::closeTag('ul'),
72
            Html::closeTag('nav'),
73
        ]);
74
    }
75
76
    protected function prepareButtons(): void
77
    {
78
        if ($this->prepared) {
79
            return;
80
        }
81
        $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

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