GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Pager::withQuery()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Tuum\Pagination;
3
4
use \Closure;
5
use Psr\Http\Message\ServerRequestInterface;
6
7
class Pager
8
{
9
    /**
10
     * a validation closure for $query input.
11
     *
12
     * @var \Closure
13
     */
14
    public $validator;
15
16
    /**
17
     * name for session storage key.
18
     *
19
     * @var string
20
     */
21
    private $name;
22
23
    /**
24
     * query key name for setting page number.
25
     *
26
     * @var string
27
     */
28
    private $pagerKey = '_page';
29
30
    /**
31
     * query key name for setting limit (per page number).
32
     *
33
     * @var string
34
     */
35
    private $limitKey = '_limit';
36
37
    /**
38
     * query for pager. maybe get from $_GET, or from session.
39
     *
40
     * @var array
41
     */
42
    private $inputs = [];
43
44
    /**
45
     * default values for input query ($this->inputs).
46
     *
47
     * @var array
48
     */
49
    private $defaultInputs = [];
50
51
    /**
52
     * path for the query.
53
     *
54
     * @var string
55
     */
56
    private $path;
57
58
    /**
59
     * @var Inputs
60
     */
61
    private $inputObject;
62
63
    /**
64
     * @param array        $default
65
     * @param null|Inputs  $inputObject
66
     */
67
    public function __construct(array $default = [], $inputObject = null)
68
    {
69
        $this->defaultInputs = $default + [
70
                $this->pagerKey => 1,
71
                $this->limitKey => 20
72
            ];
73
        $this->inputObject   = $inputObject;
74
    }
75
76
    /**
77
     * @param string $name
78
     * @param array  $default
79
     * @param null   $inputObject
80
     * @return Pager
81
     */
82
    public static function forge($name = '', array $default = [], $inputObject = null)
83
    {
84
        $self = new self($default, $inputObject);
85
        $self->name = $name ?: 'pager-' . $name;
86
        
87
        return $self;
88
    }
89
90
    /**
91
     * set a closure for validation.
92
     *
93
     * in PHP, sort of...
94
     * array_walk_recursive($_GET, $validator)
95
     *
96
     * @param Closure $validator
97
     */
98
    public function useValidator($validator)
99
    {
100
        $this->validator = $validator;
101
    }
102
103
    /**
104
     * set up pager using the PSR7 server request.
105
     *
106
     * @API
107
     * @param ServerRequestInterface $request
108
     * @return $this
109
     */
110
    public function withRequest($request)
111
    {
112
        return $this->withQuery(
113
            $request->getQueryParams(),
114
            $request->getUri()->getPath()
115
        );
116
    }
117
118
    /**
119
     * set up pager using the query data ($_GET) and pathInfo.
120
     *
121
     * @API
122
     * @param array $query query like $_GET
123
     * @param null  $path  path info
124
     * @return Pager
125
     */
126
    public function withQuery(array $query, $path = null)
127
    {
128
        $self = clone($this);
129
        $path = $path ?: htmlspecialchars($_SERVER['PATH_INFO'], ENT_QUOTES, 'UTF-8');
130
        $self->setSessionName($path);
131
        $self->loadPageKey($query);
132
        return $self;
133
    }
134
135
    /**
136
     * set query input data based on $query, or from session.
137
     *
138
     * @param array $query
139
     */
140
    private function loadPageKey($query)
141
    {
142
        if (!array_key_exists($this->pagerKey, $query)) {
143
            $this->inputs = $this->secureInput($query);
144
        } else {
145
            $this->inputs = $this->loadFromSession($query);
146
        }
147
        $this->inputs += $this->defaultInputs;
148
        $this->saveToSession();
149
    }
150
151
    /**
152
     * at least check if the input string does not have null-byte
153
     * and is a UTF-8 valid string.
154
     *
155
     * @param array $query
156
     * @return array
157
     */
158
    private function secureInput(array $query)
159
    {
160
        $secure = $this->validator ?: function (&$v) {
161
            if (!is_string($v) && !is_numeric($v)) {
162
                $v = '';
163
            } elseif (strpos($v, "\0") !== false) {
164
                $v = '';
165
            } elseif (!mb_check_encoding($v, 'UTF-8')) {
166
                $v = '';
167
            }
168
        };
169
        array_walk_recursive($query, $secure);
170
        return $query;
171
    }
172
173
    /**
174
     * load query input data from session.
175
     * the page number (pagerKey) is replaced with the input query's page.
176
     *
177
     * @param array $query
178
     * @return array
179
     */
180
    private function loadFromSession($query)
181
    {
182
        if (isset($_SESSION) && array_key_exists($this->name, $_SESSION)) {
183
            $loaded = $_SESSION[$this->name];
184
        } else {
185
            // no session. just use the $query.
186
            return $this->secureInput($query);
187
        }
188
        // check if _page is specified in $query. if so, replace it with the saved value.
189
        if (isset($query[$this->pagerKey]) && $query[$this->pagerKey] >= 1) {
190
            $loaded[$this->pagerKey] = (int)$query[$this->pagerKey];
191
        }
192
        return $loaded;
193
    }
194
195
    /**
196
     * saves $this->inputs to session.
197
     */
198
    private function saveToSession()
199
    {
200
        if (isset($_SESSION)) {
201
            $_SESSION[$this->name] = $this->inputs;
202
        }
203
    }
204
205
    /**
206
     * @param string $pathInfo
207
     */
208
    private function setSessionName($pathInfo)
209
    {
210
        $this->path = $pathInfo;
211
        $this->name = $this->name ?: 'pager-' . md5($pathInfo);
212
    }
213
214
    /**
215
     * call to construct your query based on the pager's input.
216
     *
217
     * @API
218
     * @param \Closure $closure
219
     * @return Inputs
220
     */
221
    public function call($closure)
222
    {
223
        $inputs = $this->forgeInputs();
224
        $closure($inputs);
225
        return $inputs;
226
    }
227
228
    /**
229
     * @return Inputs
230
     */
231
    public function getInputs()
232
    {
233
        return $this->forgeInputs();
234
    }
235
236
    /**
237
     * @return Inputs
238
     */
239
    private function forgeInputs()
240
    {
241
        $inputs           = $this->inputObject ? clone($this->inputObject) : new Inputs();
242
        $inputs->pagerKey = $this->pagerKey;
243
        $inputs->limitKey = $this->limitKey;
244
        $inputs->path     = $this->path;
245
        $inputs->inputs   = $this->inputs;
246
247
        return $inputs;
248
    }
249
}