Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
98.17% |
107 / 109 |
|
95.45% |
21 / 22 |
CRAP | |
0.00% |
0 / 1 |
PagerNavigationBuilder | |
98.17% |
107 / 109 |
|
95.45% |
21 / 22 |
36 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setPage | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLinkQuery | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setPrevLinkQuery | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setPrevMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setPrevTooltipMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setNextLinkQuery | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setNextMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setNextTooltipMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setFirstLinkQuery | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setFirstMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setFirstTooltipMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLastLinkQuery | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLastMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLastTooltipMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setCurrentLimit | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLimits | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLimitLinkQueryParam | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setLimitTooltipMsg | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
msg | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
makeLink | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
2 | |||
getHtml | |
96.00% |
48 / 50 |
|
0.00% |
0 / 1 |
14 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Navigation; |
4 | |
5 | use MediaWiki\Html\Html; |
6 | use MediaWiki\Language\RawMessage; |
7 | use MediaWiki\Message\Message; |
8 | use MediaWiki\Page\PageReference; |
9 | use MediaWiki\Title\Title; |
10 | use MessageLocalizer; |
11 | use RuntimeException; |
12 | |
13 | /** |
14 | * Build the navigation for a pager, with links to prev/next page, links to change limits, and |
15 | * optionally links to first/last page. |
16 | * |
17 | * @since 1.39 |
18 | */ |
19 | class PagerNavigationBuilder { |
20 | /** @var MessageLocalizer */ |
21 | private $messageLocalizer; |
22 | |
23 | /** @var PageReference */ |
24 | protected $page; |
25 | /** @var array<string,?string> */ |
26 | protected $linkQuery = []; |
27 | |
28 | /** @var array<string,?string>|null */ |
29 | private $prevLinkQuery = null; |
30 | /** @var string */ |
31 | private $prevMsg = 'prevn'; |
32 | /** @var string|null */ |
33 | private $prevTooltipMsg = null; |
34 | |
35 | /** @var array<string,?string>|null */ |
36 | private $nextLinkQuery = null; |
37 | /** @var string */ |
38 | private $nextMsg = 'nextn'; |
39 | /** @var string|null */ |
40 | private $nextTooltipMsg = null; |
41 | |
42 | /** @var array<string,?string>|null */ |
43 | private $firstLinkQuery = null; |
44 | /** @var string|null */ |
45 | private $firstMsg = null; |
46 | /** @var string|null */ |
47 | private $firstTooltipMsg = null; |
48 | |
49 | /** @var array<string,?string>|null */ |
50 | private $lastLinkQuery = null; |
51 | /** @var string|null */ |
52 | private $lastMsg = null; |
53 | /** @var string|null */ |
54 | private $lastTooltipMsg = null; |
55 | |
56 | /** @var int */ |
57 | private $currentLimit = 50; |
58 | /** @var int[] */ |
59 | private $limits = [ 20, 50, 100, 250, 500 ]; |
60 | /** @var string */ |
61 | private $limitLinkQueryParam = 'limit'; |
62 | /** @var string|null */ |
63 | private $limitTooltipMsg = null; |
64 | |
65 | /** |
66 | * @param MessageLocalizer $messageLocalizer |
67 | */ |
68 | public function __construct( MessageLocalizer $messageLocalizer ) { |
69 | $this->messageLocalizer = $messageLocalizer; |
70 | } |
71 | |
72 | /** |
73 | * @param PageReference $page |
74 | * @return $this |
75 | */ |
76 | public function setPage( PageReference $page ): PagerNavigationBuilder { |
77 | $this->page = $page; |
78 | return $this; |
79 | } |
80 | |
81 | /** |
82 | * @param array<string,?string> $linkQuery |
83 | * @return $this |
84 | */ |
85 | public function setLinkQuery( array $linkQuery ): PagerNavigationBuilder { |
86 | $this->linkQuery = $linkQuery; |
87 | return $this; |
88 | } |
89 | |
90 | /** |
91 | * @param array<string,?string>|null $prevLinkQuery |
92 | * @return $this |
93 | */ |
94 | public function setPrevLinkQuery( ?array $prevLinkQuery ): PagerNavigationBuilder { |
95 | $this->prevLinkQuery = $prevLinkQuery; |
96 | return $this; |
97 | } |
98 | |
99 | /** |
100 | * @param string $prevMsg |
101 | * @return $this |
102 | */ |
103 | public function setPrevMsg( string $prevMsg ): PagerNavigationBuilder { |
104 | $this->prevMsg = $prevMsg; |
105 | return $this; |
106 | } |
107 | |
108 | /** |
109 | * @param string|null $prevTooltipMsg |
110 | * @return $this |
111 | */ |
112 | public function setPrevTooltipMsg( ?string $prevTooltipMsg ): PagerNavigationBuilder { |
113 | $this->prevTooltipMsg = $prevTooltipMsg; |
114 | return $this; |
115 | } |
116 | |
117 | /** |
118 | * @param array<string,?string>|null $nextLinkQuery |
119 | * @return $this |
120 | */ |
121 | public function setNextLinkQuery( ?array $nextLinkQuery ): PagerNavigationBuilder { |
122 | $this->nextLinkQuery = $nextLinkQuery; |
123 | return $this; |
124 | } |
125 | |
126 | /** |
127 | * @param string $nextMsg |
128 | * @return $this |
129 | */ |
130 | public function setNextMsg( string $nextMsg ): PagerNavigationBuilder { |
131 | $this->nextMsg = $nextMsg; |
132 | return $this; |
133 | } |
134 | |
135 | /** |
136 | * @param string|null $nextTooltipMsg |
137 | * @return $this |
138 | */ |
139 | public function setNextTooltipMsg( ?string $nextTooltipMsg ): PagerNavigationBuilder { |
140 | $this->nextTooltipMsg = $nextTooltipMsg; |
141 | return $this; |
142 | } |
143 | |
144 | /** |
145 | * @param array<string,?string>|null $firstLinkQuery |
146 | * @return $this |
147 | */ |
148 | public function setFirstLinkQuery( ?array $firstLinkQuery ): PagerNavigationBuilder { |
149 | $this->firstLinkQuery = $firstLinkQuery; |
150 | return $this; |
151 | } |
152 | |
153 | /** |
154 | * @param string|null $firstMsg |
155 | * @return $this |
156 | */ |
157 | public function setFirstMsg( ?string $firstMsg ): PagerNavigationBuilder { |
158 | $this->firstMsg = $firstMsg; |
159 | return $this; |
160 | } |
161 | |
162 | /** |
163 | * @param string|null $firstTooltipMsg |
164 | * @return $this |
165 | */ |
166 | public function setFirstTooltipMsg( ?string $firstTooltipMsg ): PagerNavigationBuilder { |
167 | $this->firstTooltipMsg = $firstTooltipMsg; |
168 | return $this; |
169 | } |
170 | |
171 | /** |
172 | * @param array<string,?string>|null $lastLinkQuery |
173 | * @return $this |
174 | */ |
175 | public function setLastLinkQuery( ?array $lastLinkQuery ): PagerNavigationBuilder { |
176 | $this->lastLinkQuery = $lastLinkQuery; |
177 | return $this; |
178 | } |
179 | |
180 | /** |
181 | * @param string|null $lastMsg |
182 | * @return $this |
183 | */ |
184 | public function setLastMsg( ?string $lastMsg ): PagerNavigationBuilder { |
185 | $this->lastMsg = $lastMsg; |
186 | return $this; |
187 | } |
188 | |
189 | /** |
190 | * @param string|null $lastTooltipMsg |
191 | * @return $this |
192 | */ |
193 | public function setLastTooltipMsg( ?string $lastTooltipMsg ): PagerNavigationBuilder { |
194 | $this->lastTooltipMsg = $lastTooltipMsg; |
195 | return $this; |
196 | } |
197 | |
198 | /** |
199 | * @param int $currentLimit |
200 | * @return $this |
201 | */ |
202 | public function setCurrentLimit( int $currentLimit ): PagerNavigationBuilder { |
203 | $this->currentLimit = $currentLimit; |
204 | return $this; |
205 | } |
206 | |
207 | /** |
208 | * @param int[] $limits |
209 | * @return $this |
210 | */ |
211 | public function setLimits( array $limits ): PagerNavigationBuilder { |
212 | $this->limits = $limits; |
213 | return $this; |
214 | } |
215 | |
216 | /** |
217 | * @param string $limitLinkQueryParam |
218 | * @return $this |
219 | */ |
220 | public function setLimitLinkQueryParam( string $limitLinkQueryParam ): PagerNavigationBuilder { |
221 | $this->limitLinkQueryParam = $limitLinkQueryParam; |
222 | return $this; |
223 | } |
224 | |
225 | /** |
226 | * @param string|null $limitTooltipMsg |
227 | * @return $this |
228 | */ |
229 | public function setLimitTooltipMsg( ?string $limitTooltipMsg ): PagerNavigationBuilder { |
230 | $this->limitTooltipMsg = $limitTooltipMsg; |
231 | return $this; |
232 | } |
233 | |
234 | /** |
235 | * @param mixed $key |
236 | * @param mixed ...$params |
237 | * @return Message |
238 | */ |
239 | private function msg( $key, ...$params ): Message { |
240 | return $this->messageLocalizer |
241 | ->msg( $key, ...$params ) |
242 | ->page( $this->page ); |
243 | } |
244 | |
245 | /** |
246 | * @stable to override |
247 | * @param array|null $query |
248 | * @param string|null $class |
249 | * @param string $text |
250 | * @param string|null $tooltip |
251 | * @param string|null $rel |
252 | * @return string HTML |
253 | */ |
254 | protected function makeLink( |
255 | ?array $query, ?string $class, string $text, ?string $tooltip, ?string $rel = null |
256 | ): string { |
257 | if ( $query !== null ) { |
258 | $title = Title::newFromPageReference( $this->page ); |
259 | return Html::element( |
260 | 'a', |
261 | [ |
262 | 'href' => $title->getLocalURL( array_merge( $this->linkQuery, $query ) ), |
263 | 'rel' => $rel, |
264 | 'title' => $tooltip, |
265 | 'class' => $class, |
266 | ], |
267 | $text |
268 | ); |
269 | } else { |
270 | return Html::element( |
271 | 'span', |
272 | [ |
273 | 'class' => $class, |
274 | ], |
275 | $text |
276 | ); |
277 | } |
278 | } |
279 | |
280 | /** |
281 | * Get the navigation HTML. |
282 | * @return string HTML |
283 | */ |
284 | public function getHtml(): string { |
285 | if ( !isset( $this->page ) ) { |
286 | throw new RuntimeException( 'page must be set' ); |
287 | } |
288 | if ( isset( $this->firstMsg ) !== isset( $this->lastMsg ) ) { |
289 | throw new RuntimeException( 'firstMsg and lastMsg must be both set or both unset' ); |
290 | } |
291 | |
292 | $prevText = $this->msg( $this->prevMsg )->numParams( $this->currentLimit )->text(); |
293 | $prevTooltip = $this->prevTooltipMsg ? |
294 | $this->msg( $this->prevTooltipMsg )->numParams( $this->currentLimit )->text() : |
295 | null; |
296 | $prevLink = $this->makeLink( $this->prevLinkQuery, 'mw-prevlink', $prevText, $prevTooltip, 'prev' ); |
297 | |
298 | $nextText = $this->msg( $this->nextMsg )->numParams( $this->currentLimit )->text(); |
299 | $nextTooltip = $this->nextTooltipMsg ? |
300 | $this->msg( $this->nextTooltipMsg )->numParams( $this->currentLimit )->text() : |
301 | null; |
302 | $nextLink = $this->makeLink( $this->nextLinkQuery, 'mw-nextlink', $nextText, $nextTooltip, 'next' ); |
303 | |
304 | if ( $this->firstMsg ) { |
305 | $firstText = $this->msg( $this->firstMsg )->text(); |
306 | $firstTooltip = $this->firstTooltipMsg ? |
307 | $this->msg( $this->firstTooltipMsg )->text() : |
308 | null; |
309 | $firstLink = $this->makeLink( $this->firstLinkQuery, 'mw-firstlink', $firstText, $firstTooltip ); |
310 | } |
311 | |
312 | if ( $this->lastMsg ) { |
313 | $lastText = $this->msg( $this->lastMsg )->text(); |
314 | $lastTooltip = $this->lastTooltipMsg ? |
315 | $this->msg( $this->lastTooltipMsg )->text() : |
316 | null; |
317 | $lastLink = $this->makeLink( $this->lastLinkQuery, 'mw-lastlink', $lastText, $lastTooltip ); |
318 | } |
319 | |
320 | $limitLinks = []; |
321 | foreach ( $this->limits as $limit ) { |
322 | $limitText = $this->msg( new RawMessage( '$1' ) )->numParams( $limit )->text(); |
323 | $limitTooltip = $this->limitTooltipMsg ? |
324 | $this->msg( $this->limitTooltipMsg )->numParams( $limit )->text() : |
325 | null; |
326 | $limitQuery = $limit === $this->currentLimit ? null : [ $this->limitLinkQueryParam => $limit ]; |
327 | $limitLinks[] = $this->makeLink( $limitQuery, 'mw-numlink', $limitText, $limitTooltip ); |
328 | } |
329 | |
330 | $html = ''; |
331 | if ( isset( $firstLink ) && isset( $lastLink ) ) { |
332 | $html .= $this->msg( 'parentheses' )->params( |
333 | Message::listParam( [ |
334 | Message::rawParam( $firstLink ), |
335 | Message::rawParam( $lastLink ) |
336 | ], 'pipe' ) |
337 | )->escaped() . ' '; |
338 | } |
339 | $html .= $this->msg( 'viewprevnext' )->params( |
340 | Message::rawParam( $prevLink ), |
341 | Message::rawParam( $nextLink ), |
342 | Message::listParam( array_map( static function ( $limitLink ) { |
343 | return Message::rawParam( $limitLink ); |
344 | }, $limitLinks ), 'pipe' ) |
345 | )->escaped(); |
346 | |
347 | return Html::rawElement( 'div', [ 'class' => 'mw-pager-navigation-bar' ], $html ); |
348 | } |
349 | } |