Index: trunk/phase3/includes/SpecialWhatlinkshere.php |
— | — | @@ -88,59 +88,80 @@ |
89 | 89 | } |
90 | 90 | |
91 | 91 | // Make the query |
| 92 | + $plConds = array( |
| 93 | + 'page_id=pl_from', |
| 94 | + 'pl_namespace' => $target->getNamespace(), |
| 95 | + 'pl_title' => $target->getDBkey(), |
| 96 | + ); |
| 97 | + |
| 98 | + $tlConds = array( |
| 99 | + 'page_id=tl_from', |
| 100 | + 'tl_namespace' => $target->getNamespace(), |
| 101 | + 'tl_title' => $target->getDBkey(), |
| 102 | + ); |
| 103 | + |
92 | 104 | if ( $from ) { |
93 | 105 | if ( 'prev' == $dir ) { |
94 | | - $offsetCond = "AND page_id < $from"; |
95 | | - $options = 'ORDER BY page_id DESC,is_template DESC'; |
| 106 | + $offsetCond = "page_id < $from"; |
| 107 | + $options = array( 'ORDER BY page_id DESC' ); |
96 | 108 | } else { |
97 | | - $offsetCond = "AND page_id >= $from"; |
98 | | - $options = 'ORDER BY page_id, is_template DESC'; |
| 109 | + $offsetCond = "page_id >= $from"; |
| 110 | + $options = array( 'ORDER BY page_id' ); |
99 | 111 | } |
100 | 112 | } else { |
101 | | - $offsetCond = ''; |
102 | | - $options = 'ORDER BY page_id,is_template DESC'; |
| 113 | + $offsetCond = false; |
| 114 | + $options = array( 'ORDER BY page_id,is_template DESC' ); |
103 | 115 | } |
104 | 116 | // Read an extra row as an at-end check |
105 | 117 | $queryLimit = $limit + 1; |
106 | | - $options .= ' LIMIT ' . $queryLimit; |
107 | | - |
108 | | - $ns = $dbr->addQuotes( $target->getNamespace() ); |
109 | | - $dbk = $dbr->addQuotes( $target->getDBkey() ); |
110 | | - $plCond = "page_id=pl_from AND pl_namespace=$ns AND pl_title=$dbk"; |
111 | | - $tlCond = "page_id=tl_from AND tl_namespace=$ns AND tl_title=$dbk"; |
| 118 | + $options['LIMIT'] = $queryLimit; |
| 119 | + if ( $offsetCond ) { |
| 120 | + $tlConds[] = $offsetCond; |
| 121 | + $plConds[] = $offsetCond; |
| 122 | + } |
| 123 | + $fields = array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ); |
112 | 124 | |
113 | | - // Make a union query which will read both templatelinks and pagelinks, |
114 | | - // with an is_template field in the output indicating which one the link |
115 | | - // came from |
116 | | - $sql = "(SELECT page_id,page_namespace, page_title, page_is_redirect, 1 as is_template " . |
117 | | - "FROM page, templatelinks WHERE $tlCond $offsetCond $options) " . |
118 | | - "UNION (SELECT page_id,page_namespace, page_title, page_is_redirect, 0 as is_template " . |
119 | | - "FROM page, pagelinks WHERE $plCond $offsetCond $options) $options"; |
120 | | - $res = $dbr->query( $sql, $fname ); |
121 | | - $numRows = $dbr->numRows( $res ); |
122 | | - |
123 | | - if ( 0 == $numRows ) { |
| 125 | + $plRes = $dbr->select( array( 'pagelinks', 'page' ), $fields, |
| 126 | + $plConds, $fname, $options ); |
| 127 | + $tlRes = $dbr->select( array( 'templatelinks', 'page' ), $fields, |
| 128 | + $tlConds, $fname, $options ); |
| 129 | + |
| 130 | + if ( !$dbr->numRows( $plRes ) && !$dbr->numRows( $tlRes ) ) { |
124 | 131 | if ( 0 == $level ) { |
125 | 132 | $wgOut->addWikiText( wfMsg( 'nolinkshere' ) ); |
126 | 133 | } |
127 | 134 | return; |
| 135 | + } |
| 136 | + |
| 137 | + // Read the rows into an array and remove duplicates |
| 138 | + // templatelinks comes second so that the templatelinks row overwrites the |
| 139 | + // pagelinks row, so we get (inclusion) rather than nothing |
| 140 | + while ( $row = $dbr->fetchObject( $plRes ) ) { |
| 141 | + $row->is_template = 0; |
| 142 | + $rows[$row->page_id] = $row; |
128 | 143 | } |
| 144 | + $dbr->freeResult( $plRes ); |
| 145 | + while ( $row = $dbr->fetchObject( $tlRes ) ) { |
| 146 | + $row->is_template = 1; |
| 147 | + $rows[$row->page_id] = $row; |
| 148 | + } |
| 149 | + $dbr->freeResult( $tlRes ); |
129 | 150 | |
130 | | - // Read the rows into an array |
131 | | - $rows = array(); |
132 | | - while ( $row = $dbr->fetchObject( $res ) ) { |
133 | | - $rows[] = $row; |
134 | | - } |
135 | | - $lastRow = end( $rows ); |
| 151 | + // Sort by key and then change the keys to 0-based indices |
| 152 | + ksort( $rows ); |
| 153 | + $rows = array_values( $rows ); |
| 154 | + |
| 155 | + $numRows = count( $rows ); |
| 156 | + |
136 | 157 | // Work out the start and end IDs, for prev/next links |
137 | 158 | if ( $dir == 'prev' ) { |
138 | 159 | // Descending order |
139 | | - if ( $numRows == $queryLimit ) { |
| 160 | + if ( $numRows > $limit ) { |
140 | 161 | // More rows available before these ones |
141 | | - // Get the ID from the last row in the result set |
142 | | - $prevId = $lastRow->page_id; |
143 | | - // Remove undisplayed row |
144 | | - unset( $rows[$queryLimit - 1] ); |
| 162 | + // Get the ID from the next row past the end of the displayed set |
| 163 | + $prevId = $rows[$limit]->page_id; |
| 164 | + // Remove undisplayed rows |
| 165 | + $rows = array_slice( $rows, 0, $limit ); |
145 | 166 | } else { |
146 | 167 | // No more rows available before |
147 | 168 | $prevId = 0; |
— | — | @@ -148,16 +169,16 @@ |
149 | 170 | // Assume that the ID specified in $from exists, so there must be another page |
150 | 171 | $nextId = $from; |
151 | 172 | |
152 | | - // Reverse order |
| 173 | + // Reverse order ready for display |
153 | 174 | $rows = array_reverse( $rows ); |
154 | 175 | } else { |
155 | 176 | // Ascending |
156 | | - if ( $numRows == $queryLimit ) { |
| 177 | + if ( $numRows > $limit ) { |
157 | 178 | // More rows available after these ones |
158 | 179 | // Get the ID from the last row in the result set |
159 | | - $nextId = $lastRow->page_id; |
160 | | - // Remove undisplayed row |
161 | | - unset( $rows[$queryLimit - 1] ); |
| 180 | + $nextId = $rows[$limit]->page_id; |
| 181 | + // Remove undisplayed rows |
| 182 | + $rows = array_slice( $rows, 0, $limit ); |
162 | 183 | } else { |
163 | 184 | // No more rows after |
164 | 185 | $nextId = false; |
— | — | @@ -177,18 +198,7 @@ |
178 | 199 | } |
179 | 200 | |
180 | 201 | $wgOut->addHTML( '<ul>' ); |
181 | | - $linksShown = 0; |
182 | | - $lastNs = false; |
183 | | - $lastDbk = false; |
184 | 202 | foreach ( $rows as $row ) { |
185 | | - if ( $lastNs === $row->page_namespace && $lastDbk === $row->page_title ) { |
186 | | - // Skip duplicates |
187 | | - continue; |
188 | | - } else { |
189 | | - $lastNs = $row->page_namespace; |
190 | | - $lastDbk = $row->page_title; |
191 | | - } |
192 | | - |
193 | 203 | $nt = Title::makeTitle( $row->page_namespace, $row->page_title ); |
194 | 204 | |
195 | 205 | if ( $row->page_is_redirect ) { |