RequestFilter::createPaginator()   A
last analyzed

Complexity

Conditions 6
Paths 12

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 6.1666

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 29
ccs 15
cts 18
cp 0.8333
rs 9.0444
c 0
b 0
f 0
cc 6
nc 12
nop 2
crap 6.1666
1
<?php
2
3
namespace kalanis\Restful\Utils;
4
5
6
use kalanis\Restful\Exceptions\InvalidStateException;
7
use Nette\Http\IRequest;
8
use Nette\Utils\Paginator;
9
10
11
/**
12
 * RequestFilter
13
 * @package kalanis\Restful\Utils
14
 */
15
class RequestFilter
16
{
17
18
    /** Fields key in URL query */
19
    public const FIELDS_KEY = 'fields';
20
    /** Sort key in URL query */
21
    public const SORT_KEY = 'sort';
22
    /** Search string key in URL query */
23
    public const SEARCH_KEY = 'q';
24
25
    /** Descending sort */
26
    public const SORT_DESC = 'DESC';
27
    /** Ascending sort */
28
    public const SORT_ASC = 'ASC';
29
30
    /** @var array<string> */
31
    private array $fieldList = [];
32
    /** @var array<string, string> */
33
    private array $sortList = [];
34
    private ?Paginator $paginator = null;
35
36 1
    public function __construct(
37
        private readonly IRequest $request,
38
    )
39
    {
40 1
    }
41
42
    /**
43
     * Get fields list
44
     * @return array<string>
45
     */
46
    public function getFieldList(): array
47
    {
48 1
        if (empty($this->fieldList)) {
49 1
            $this->fieldList = $this->createFieldList();
50
        }
51 1
        return $this->fieldList;
52
    }
53
54
    /**
55
     * Create field list
56
     * @return array<string>
57
     */
58
    protected function createFieldList(): array
59
    {
60 1
        $fields = $this->request->getQuery(self::FIELDS_KEY);
61 1
        return is_string($fields)
62 1
            ? array_filter(explode(',', $fields))
63 1
            : array_filter(array_map(fn($val) => strval($val), (array) $fields))
64
        ;
65
    }
66
67
    /**
68
     * Create sort list
69
     * @return array<string, string>
70
     */
71
    public function getSortList(): array
72
    {
73 1
        if (empty($this->sortList)) {
74 1
            $this->sortList = $this->createSortList();
75
        }
76 1
        return $this->sortList;
77
    }
78
79
    /**
80
     * Create sort list
81
     * @return array<string, string>
82
     */
83
    protected function createSortList(): array
84
    {
85 1
        $sortList = [];
86 1
        $fields = array_filter(explode(',', strval($this->request->getQuery(self::SORT_KEY))));
87 1
        foreach ($fields as $field) {
88 1
            $isInverted = '-' === Strings::substring($field, 0, 1);
89 1
            $sort = $isInverted ? self::SORT_DESC : self::SORT_ASC;
90 1
            $field = $isInverted ? Strings::substring($field, 1) : $field;
91 1
            $sortList[$field] = $sort;
92
        }
93 1
        return $sortList;
94
    }
95
96
    /**
97
     * Get search query
98
     * @return mixed
99
     */
100
    public function getSearchQuery(): mixed
101
    {
102 1
        return $this->request->getQuery('q');
103
    }
104
105
    /**
106
     * Get paginator
107
     * @param int|null $offset default value
108
     * @param int|null $limit default value
109
     * @throws InvalidStateException
110
     * @return Paginator
111
     */
112
    public function getPaginator(?int $offset = null, ?int $limit = null): Paginator
113
    {
114 1
        if (empty($this->paginator)) {
115 1
            $this->paginator = $this->createPaginator($offset, $limit);
116
        }
117 1
        return $this->paginator;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->paginator could return the type null which is incompatible with the type-hinted return Nette\Utils\Paginator. Consider adding an additional type-check to rule them out.
Loading history...
118
    }
119
120
    /**
121
     * Create paginator
122
     * @param int|null $offset
123
     * @param int|null $limit
124
     * @throws InvalidStateException
125
     * @return Paginator
126
     */
127
    protected function createPaginator(?int $offset = null, ?int $limit = null): Paginator
128
    {
129 1
        $off = $this->request->getQuery('offset');
130 1
        if (empty($off)) {
131
            $off = $offset;
132
        }
133 1
        $lim = $this->request->getQuery('limit');
134 1
        if (empty($lim)) {
135 1
            $lim = $limit;
136
        }
137
138 1
        if (is_null($off) || is_null($lim)) {
139 1
            throw new InvalidStateException(
140 1
                'To create paginator add offset and limit query parameter to request URL'
141
            );
142
        }
143 1
        $lim = intval($lim);
144 1
        $off = intval($off);
145
146 1
        if (0 == $lim) {
147
            throw new InvalidStateException(
148
                'Pagination limit cannot be zero'
149
            );
150
        }
151
152 1
        $paginator = new Paginator();
153 1
        $paginator->setItemsPerPage($lim);
154 1
        $paginator->setPage(intval(floor($off / $lim)) + 1);
155 1
        return $paginator;
156
    }
157
}
158