Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.88% |
46 / 49 |
|
80.00% |
4 / 5 |
CRAP | |
0.00% |
0 / 1 |
PageList | |
93.88% |
46 / 49 |
|
80.00% |
4 / 5 |
31.22 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getNumber | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
buildNumber | |
100.00% |
31 / 31 |
|
100.00% |
1 / 1 |
15 | |||
numberInRange | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
10 | |||
getRangeStart | |
57.14% |
4 / 7 |
|
0.00% |
0 / 1 |
3.71 |
1 | <?php |
2 | |
3 | namespace ProofreadPage\Pagination; |
4 | |
5 | use RuntimeException; |
6 | |
7 | /** |
8 | * @license GPL-2.0-or-later |
9 | * |
10 | * Representation for a <pagelist> tag |
11 | */ |
12 | class PageList { |
13 | |
14 | /** |
15 | * @var array parameters of the <pagelist> tag |
16 | */ |
17 | private $params; |
18 | |
19 | /** |
20 | * @var PageNumber[] PageNumber already computed |
21 | */ |
22 | private $pageNumbers = []; |
23 | |
24 | /** |
25 | * @param array $params parameters of the <pagelist> tag |
26 | */ |
27 | public function __construct( array $params ) { |
28 | $this->params = $params; |
29 | } |
30 | |
31 | /** |
32 | * Returns the PageNumber for the page number $pageNumber |
33 | * |
34 | * @param int $pageNumber |
35 | * @return PageNumber |
36 | */ |
37 | public function getNumber( int $pageNumber ): PageNumber { |
38 | if ( !array_key_exists( $pageNumber, $this->pageNumbers ) ) { |
39 | $this->pageNumbers[$pageNumber] = $this->buildNumber( $pageNumber ); |
40 | } |
41 | |
42 | return $this->pageNumbers[$pageNumber]; |
43 | } |
44 | |
45 | /** |
46 | * Returns the PageNumber for the page number $pageNumber |
47 | * |
48 | * @param int $pageNumber |
49 | * @return PageNumber |
50 | */ |
51 | private function buildNumber( int $pageNumber ): PageNumber { |
52 | // default mode |
53 | $mode = PageNumber::DISPLAY_NORMAL; |
54 | $offset = 0; |
55 | $displayedPageNumber = ''; |
56 | $isEmpty = false; |
57 | $isRecto = true; |
58 | |
59 | foreach ( $this->params as $num => $parameters ) { |
60 | if ( is_numeric( $num ) && $num <= $pageNumber ) { |
61 | $params = explode( ';', $parameters ); |
62 | foreach ( $params as $param ) { |
63 | if ( is_numeric( $param ) ) { |
64 | $offset = $num - (int)$param; |
65 | } |
66 | } |
67 | } |
68 | |
69 | if ( $this->numberInRange( $num, $pageNumber ) ) { |
70 | $params = explode( ';', $parameters ); |
71 | foreach ( $params as $param ) { |
72 | if ( !is_numeric( $param ) ) { |
73 | if ( in_array( $param, PageNumber::getDisplayModes(), true ) ) { |
74 | $mode = $param; |
75 | } elseif ( $param == PageNumber::DISPLAY_EMPTY ) { |
76 | $isEmpty = true; |
77 | } else { |
78 | $displayedPageNumber = $param; |
79 | } |
80 | } |
81 | } |
82 | |
83 | if ( $mode == PageNumber::DISPLAY_FOLIO |
84 | || $mode == PageNumber::DISPLAY_FOLIOHIGHROMAN |
85 | || $mode == PageNumber::DISPLAY_FOLIOROMAN ) { |
86 | $folioStart = $this->getRangeStart( $num ); |
87 | $displayedPageNumber = (int)$folioStart - $offset |
88 | + (int)( ( $pageNumber - (int)$folioStart ) / 2 ); |
89 | |
90 | $isRecto = ( $pageNumber - (int)$folioStart ) % 2 === 0; |
91 | } |
92 | } |
93 | } |
94 | |
95 | $displayedPageNumber = ( $displayedPageNumber === '' ) |
96 | ? $pageNumber - $offset |
97 | : $displayedPageNumber; |
98 | return new PageNumber( $displayedPageNumber, $mode, $isEmpty, $isRecto ); |
99 | } |
100 | |
101 | /** |
102 | * Returns if a number is in a range as defined by <pagelist> |
103 | * Such range may be a single integer or something in the format XXtoYY |
104 | * |
105 | * @param string $range |
106 | * @param int $number |
107 | * @return bool |
108 | */ |
109 | protected function numberInRange( string $range, int $number ): bool { |
110 | return ( is_numeric( $range ) && $range == $number ) || |
111 | ( preg_match( '/^([0-9]*)to([0-9]*)((even|odd)?)$/', $range, $m ) && |
112 | $m[1] <= $number && $number <= $m[2] && |
113 | ( $m[3] === '' |
114 | || ( $m[3] === 'even' && $number % 2 === 0 ) |
115 | || ( $m[3] === 'odd' && $number % 2 === 1 ) ) |
116 | ); |
117 | } |
118 | |
119 | /** |
120 | * @param string $range |
121 | * @return string |
122 | * @throws RuntimeException |
123 | */ |
124 | private function getRangeStart( string $range ): string { |
125 | if ( is_numeric( $range ) ) { |
126 | return $range; |
127 | } elseif ( preg_match( '/^([0-9]*)to([0-9]*)((even|odd)?)$/', $range, $m ) ) { |
128 | return $m[1]; |
129 | } else { |
130 | throw new RuntimeException( |
131 | $range . ' is not a valid range.' |
132 | ); |
133 | } |
134 | } |
135 | } |