Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 222 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
CalendarTable | |
0.00% |
0 / 222 |
|
0.00% |
0 / 12 |
7140 | |
0.00% |
0 / 1 |
dayOfWeek | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isLeapYear | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
dayOfWeekOfFirstOfMonth | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getMonthName | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getMonthNameAbbrev | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getWeekday | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
getWeekdayAbbrev | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
cutLength | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getLang | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
replace | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
buildTable | |
0.00% |
0 / 74 |
|
0.00% |
0 / 1 |
1056 | |||
setParameters | |
0.00% |
0 / 127 |
|
0.00% |
0 / 1 |
1560 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Extension\Calendar; |
4 | |
5 | use DateTime; |
6 | use MediaWiki\Language\Language; |
7 | use MediaWiki\MediaWikiServices; |
8 | |
9 | class CalendarTable { |
10 | |
11 | /** @var string */ |
12 | protected $lng = 'content'; |
13 | /** @var string */ |
14 | protected $prevLink = ''; |
15 | /** @var string */ |
16 | protected $nextLink = ''; |
17 | /** @var string */ |
18 | protected $calTitle = ''; |
19 | /** @var string[] */ |
20 | protected $highlightedDays = []; |
21 | /** @var string[] */ |
22 | protected $dailyLinks = []; |
23 | /** @var int */ |
24 | protected $weekStart = 0; |
25 | /** @var string */ |
26 | protected $position = ''; |
27 | /** @var string */ |
28 | protected $titleLink = ''; |
29 | /** @var string */ |
30 | protected $generalLinks = ''; |
31 | /** @var int */ |
32 | protected $dayCharsCount = 0; |
33 | /** @var int */ |
34 | protected $monthCharsCount = 0; |
35 | /** @var string */ |
36 | protected $tableWidth = 'default'; |
37 | /** @var bool */ |
38 | protected $showToday = true; |
39 | |
40 | /** @var DateTime */ |
41 | protected $today; |
42 | /** @var int */ |
43 | protected $curDay; |
44 | /** @var int */ |
45 | protected $curMonth; |
46 | /** @var int */ |
47 | protected $curYear; |
48 | /** @var int */ |
49 | protected $month; |
50 | /** @var int */ |
51 | protected $year; |
52 | /** @var string[] */ |
53 | protected $monthArr; |
54 | /** @var string[] */ |
55 | protected $dayArr; |
56 | |
57 | /** |
58 | * @param int $timestamp |
59 | * @return int |
60 | */ |
61 | public function dayOfWeek( $timestamp ) { |
62 | return intval( date( 'w', $timestamp ) ); |
63 | } |
64 | |
65 | /** |
66 | * @param int $aYear |
67 | * @return bool |
68 | */ |
69 | public function isLeapYear( $aYear ) { |
70 | return cal_days_in_month( CAL_GREGORIAN, 2, $aYear ) === 29; |
71 | } |
72 | |
73 | /** |
74 | * @param int $aMonth |
75 | * @param int $aYear |
76 | * @return int |
77 | */ |
78 | public function dayOfWeekOfFirstOfMonth( $aMonth, $aYear ) { |
79 | return $this->dayOfWeek( mktime( 0, 0, 0, $aMonth, 1, $aYear ) ); |
80 | } |
81 | |
82 | /** |
83 | * @param int $aMonth |
84 | * @param int $aLen |
85 | * @return string |
86 | */ |
87 | public function getMonthName( $aMonth, $aLen ) { |
88 | $out = $this->getLang()->getMonthName( $aMonth ); |
89 | return $this->cutLength( $out, $aLen ); |
90 | } |
91 | |
92 | /** |
93 | * @param int $aMonth |
94 | * @param int $aLen |
95 | * @return string |
96 | */ |
97 | public function getMonthNameAbbrev( $aMonth, $aLen ) { |
98 | $out = $this->getLang()->getMonthAbbreviation( $aMonth ); |
99 | return $this->cutLength( $out, $aLen ); |
100 | } |
101 | |
102 | /** |
103 | * @param int $aDay |
104 | * @param int $aLen |
105 | * @return string |
106 | */ |
107 | public function getWeekday( $aDay, $aLen ) { |
108 | // Language::getWeekdayName will subtract 1 from key |
109 | $out = $this->getLang()->getWeekdayName( $aDay % 7 + 1 ); |
110 | return $this->cutLength( $out, $aLen ); |
111 | } |
112 | |
113 | /** |
114 | * @param int $aDay |
115 | * @param int $aLen |
116 | * @return string |
117 | */ |
118 | public function getWeekdayAbbrev( $aDay, $aLen ) { |
119 | // Language::getWeekdayAbbreviation will subtract 1 from key |
120 | $out = $this->getLang()->getWeekdayAbbreviation( $aDay % 7 + 1 ); |
121 | return $this->cutLength( $out, $aLen ); |
122 | } |
123 | |
124 | /** |
125 | * @param string $string |
126 | * @param int $len |
127 | * @return string |
128 | */ |
129 | private function cutLength( $string, $len ) { |
130 | if ( $len > 0 ) { |
131 | $string = mb_substr( $string, 0, $len ); |
132 | } |
133 | return ucfirst( $string ); |
134 | } |
135 | |
136 | /** |
137 | * @return Language |
138 | */ |
139 | private function getLang() { |
140 | if ( $this->lng === 'user' ) { |
141 | global $wgLang; |
142 | return $wgLang; |
143 | } |
144 | return MediaWikiServices::getInstance()->getContentLanguage(); |
145 | } |
146 | |
147 | /** |
148 | * @param string $str |
149 | * @param string[] $array |
150 | * @return string |
151 | */ |
152 | public function replace( $str, array $array ) { |
153 | foreach ( $array as $key => $val ) { |
154 | $str = str_replace( '$' . $key, $val, $str ); |
155 | } |
156 | return str_replace( '$%', '$', $str ); |
157 | } |
158 | |
159 | /** |
160 | * @return string |
161 | */ |
162 | public function buildTable() { |
163 | $day1 = $this->dayOfWeekOfFirstOfMonth( $this->month, $this->year ); |
164 | if ( ( $this->weekStart > 0 ) && ( $day1 === 0 ) ) { |
165 | $day1 = 7; |
166 | } |
167 | $days = cal_days_in_month( CAL_GREGORIAN, $this->month, $this->year ); |
168 | |
169 | $style = ''; |
170 | $result = 'calendar'; |
171 | switch ( $this->position ) { |
172 | case 'left': |
173 | $result .= ' calLeft'; |
174 | break; |
175 | case 'right': |
176 | $result .= ' calRight'; |
177 | break; |
178 | case 'center': |
179 | $result .= ' calCenter'; |
180 | $style = ' align="center"'; |
181 | } |
182 | |
183 | if ( $this->tableWidth === 'default' ) { |
184 | $result .= ' calWidth'; |
185 | } elseif ( $this->tableWidth !== 'none' ) { |
186 | $style .= ' style="width: ' . $this->tableWidth . '"'; |
187 | } |
188 | $result = '{| class="' . $result . '"' . $style . "\n|-\n"; |
189 | |
190 | $colSpan = 5; |
191 | if ( $this->calTitle === '' ) { |
192 | $this->calTitle = $this->getMonthName( $this->month, $this->monthCharsCount ) |
193 | . ' ' . $this->year; |
194 | } |
195 | if ( $this->titleLink !== '' ) { |
196 | $this->calTitle = '[[' . $this->titleLink . '|' . $this->calTitle . ']]'; |
197 | } |
198 | if ( $this->nextLink === '' ) { |
199 | $colSpan++; |
200 | } |
201 | if ( $this->prevLink === '' ) { |
202 | $colSpan++; |
203 | } else { |
204 | $result .= '| class="prevNext" | ' . $this->prevLink . "\n"; |
205 | } |
206 | $result .= '| class="calTitle" colspan="' . $colSpan . '" | ' . $this->calTitle . "\n"; |
207 | if ( $this->nextLink !== '' ) { |
208 | $result .= '| class="prevNext" | ' . $this->nextLink . "\n"; |
209 | } |
210 | |
211 | $result .= "|-\n"; |
212 | for ( $i = $this->weekStart; $i < 7; $i++ ) { |
213 | $result .= "! " . $this->getWeekdayAbbrev( $i, $this->dayCharsCount ) . "\n"; |
214 | } |
215 | if ( $this->weekStart > 0 ) { |
216 | for ( $i = 0; $i < $this->weekStart; $i++ ) { |
217 | $result .= "! " . $this->getWeekdayAbbrev( $i, $this->dayCharsCount ) . "\n"; |
218 | } |
219 | } |
220 | |
221 | $c = 1 - $day1 + $this->weekStart; |
222 | while ( $c <= $days ) { |
223 | $result .= "|-\n"; |
224 | for ( $i = 0; $i < 7; $i++ ) { |
225 | $this->dayArr['a'] = $this->getWeekdayAbbrev( $i + $this->weekStart, 0 ); |
226 | $this->dayArr['A'] = $this->getWeekday( $i + $this->weekStart, 0 ); |
227 | $this->dayArr['D'] = (string)$c; |
228 | $this->dayArr['d'] = sprintf( '%02s', $c ); |
229 | $this->dayArr['e'] = sprintf( '%2s', $c ); |
230 | $styles = []; |
231 | if ( $i === 0 && $this->weekStart === 0 ) { |
232 | $styles[] = 'sundays'; |
233 | } elseif ( $i === 6 && $this->weekStart === 1 ) { |
234 | $styles[] = 'sundays'; |
235 | } |
236 | if ( $this->showToday && ( $c === $this->curDay ) && ( $this->curMonth === $this->month ) |
237 | && ( $this->curYear === $this->year ) |
238 | ) { |
239 | $styles[] = 'today'; |
240 | } |
241 | if ( in_array( $c, $this->highlightedDays ) ) { |
242 | $styles[] = 'highlighted'; |
243 | } |
244 | $allStyles = implode( ' ', $styles ); |
245 | if ( $allStyles === '' ) { |
246 | $result .= '| '; |
247 | } else { |
248 | $result .= '| class="' . $allStyles . '" | '; |
249 | } |
250 | if ( $c > 0 && $c <= $days ) { |
251 | if ( $this->dailyLinks[$c] != '' ) { |
252 | $result .= '[[' . $this->dailyLinks[$c] . '|' . $c . ']]'; |
253 | } elseif ( $this->generalLinks != '' ) { |
254 | $result .= '[[' . $this->replace( $this->generalLinks, $this->dayArr ) . '|' . $c . ']]'; |
255 | } else { |
256 | $result .= $c; |
257 | } |
258 | } else { |
259 | $result .= ' '; |
260 | } |
261 | $result .= "\n"; |
262 | $c++; |
263 | } |
264 | } |
265 | return $result . "|}\n"; |
266 | } |
267 | |
268 | /** |
269 | * @param array $args |
270 | */ |
271 | public function setParameters( array $args ) { |
272 | $this->today = new DateTime( "now" ); |
273 | $this->curDay = intval( $this->today->format( "d" ) ); |
274 | $this->curMonth = intval( $this->today->format( "m" ) ); |
275 | $this->curYear = intval( $this->today->format( "Y" ) ); |
276 | $this->month = $this->curMonth; |
277 | $this->year = $this->curYear; |
278 | for ( $i = 0; $i < 32; $i++ ) { |
279 | $this->dailyLinks[$i] = ''; |
280 | } |
281 | $offset = 0; |
282 | |
283 | foreach ( $args as $arg ) { |
284 | $parts = array_map( 'trim', explode( '=', $arg, 2 ) ); |
285 | if ( ( count( $parts ) === 2 ) && ( $parts[0] > 0 ) && ( $parts[0] < 32 ) ) { |
286 | $this->dailyLinks[$parts[0]] = $parts[1]; |
287 | } else { |
288 | if ( count( $parts ) !== 2 ) { |
289 | continue; |
290 | } |
291 | switch ( $parts[0] ) { |
292 | case 'month': |
293 | $this->month = intval( $parts[1] ); |
294 | break; |
295 | case 'year': |
296 | $this->year = intval( $parts[1] ); |
297 | break; |
298 | case 'offset': |
299 | $offset = intval( $parts[1] ); |
300 | break; |
301 | case 'lang': |
302 | $this->lng = strtolower( $parts[1] ); |
303 | if ( $this->lng !== 'user' ) { |
304 | $this->lng = 'content'; |
305 | } |
306 | break; |
307 | case 'prevLink': |
308 | $this->prevLink = $parts[1]; |
309 | break; |
310 | case 'nextLink': |
311 | $this->nextLink = $parts[1]; |
312 | break; |
313 | case 'title': |
314 | $this->calTitle = $parts[1]; |
315 | break; |
316 | case 'highlightedDays': |
317 | $this->highlightedDays = |
318 | preg_split( '/\s+/', $parts[1], 32, PREG_SPLIT_NO_EMPTY ); |
319 | break; |
320 | case 'start': |
321 | $this->weekStart = (int)$parts[1]; |
322 | if ( $this->weekStart !== 1 ) { |
323 | $this->weekStart = 0; |
324 | } |
325 | break; |
326 | case 'position': |
327 | $this->position = strtolower( $parts[1] ); |
328 | break; |
329 | case 'titleLink': |
330 | $this->titleLink = $parts[1]; |
331 | break; |
332 | case 'generalLinks': |
333 | $this->generalLinks = $parts[1]; |
334 | break; |
335 | case 'dayCharsCount': |
336 | $this->dayCharsCount = intval( $parts[1] ); |
337 | if ( $this->dayCharsCount < 0 ) { |
338 | $this->dayCharsCount = 0; |
339 | } |
340 | break; |
341 | case 'monthCharsCount': |
342 | $this->monthCharsCount = intval( $parts[1] ); |
343 | if ( $this->monthCharsCount < 0 ) { |
344 | $this->monthCharsCount = 0; |
345 | } |
346 | break; |
347 | case 'tableWidth': |
348 | $this->tableWidth = $parts[1]; |
349 | if ( $this->tableWidth !== 'default' && $this->tableWidth !== 'none' |
350 | && preg_match( '/^\d+(\%|em|ex|pc|pt|px|in|mm|cm)$/', $this->tableWidth ) == 0 |
351 | ) { |
352 | $this->tableWidth = 'default'; |
353 | } |
354 | break; |
355 | case 'showToday': |
356 | $this->showToday = $parts[1] === 'true'; |
357 | break; |
358 | } |
359 | } |
360 | } |
361 | |
362 | if ( ( $this->month < 1 ) || ( $this->month > 12 ) ) { |
363 | $this->month = $this->curMonth; |
364 | $this->year = $this->curYear; |
365 | } |
366 | |
367 | if ( $offset != 0 ) { |
368 | $offM = $offset % 12; |
369 | $offset = (int)round( ( $offset - $offM ) / 12 ); |
370 | $this->month += $offM; |
371 | $this->year += $offset; |
372 | if ( $this->month > 12 ) { |
373 | $this->month -= 12; |
374 | $this->year++; |
375 | } |
376 | if ( $this->month < 1 ) { |
377 | $this->month += 12; |
378 | $this->year--; |
379 | } |
380 | } |
381 | if ( $this->year < 1970 ) { |
382 | $this->month = 1; |
383 | $this->year = 1970; |
384 | } elseif ( $this->year > 2037 ) { |
385 | $this->month = 12; |
386 | $this->year = 2037; |
387 | } |
388 | |
389 | $prevMonthYear = $this->year; |
390 | $prevMonth = $this->month - 1; |
391 | if ( $prevMonth == 0 ) { |
392 | $prevMonth = 12; |
393 | $prevMonthYear--; |
394 | } |
395 | $nextMonthYear = $this->year; |
396 | $nextMonth = $this->month + 1; |
397 | if ( $nextMonth == 13 ) { |
398 | $nextMonth = 1; |
399 | $nextMonthYear++; |
400 | } |
401 | $this->monthArr = [ |
402 | 'b' => $this->getMonthNameAbbrev( $this->month, 0 ), |
403 | 'B' => $this->getMonthName( $this->month, 0 ), |
404 | 'm' => sprintf( '%02s', $this->month ), |
405 | 'M' => sprintf( '%02s', $nextMonth ), |
406 | 'n' => $this->getMonthNameAbbrev( $nextMonth, 0 ), |
407 | 'N' => $this->getMonthName( $nextMonth, 0 ), |
408 | 'o' => substr( (string)$nextMonthYear, 2, 2 ), |
409 | 'O' => (string)$nextMonthYear, |
410 | 'p' => $this->getMonthNameAbbrev( $prevMonth, 0 ), |
411 | 'P' => $this->getMonthName( $prevMonth, 0 ), |
412 | 'q' => substr( (string)$prevMonthYear, 2, 2 ), |
413 | 'Q' => (string)$prevMonthYear, |
414 | 'R' => sprintf( '%02s', $prevMonth ), |
415 | 'y' => substr( (string)$this->year, 2, 2 ), |
416 | 'Y' => (string)$this->year |
417 | ]; |
418 | $this->dayArr = $this->monthArr; |
419 | $this->titleLink = $this->replace( $this->titleLink, $this->monthArr ); |
420 | $this->prevLink = $this->replace( $this->prevLink, $this->monthArr ); |
421 | $this->nextLink = $this->replace( $this->nextLink, $this->monthArr ); |
422 | } |
423 | } |