Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -1285,6 +1285,7 @@ |
1286 | 1286 | 'nextpage', |
1287 | 1287 | 'prevpage', |
1288 | 1288 | 'allpagesfrom', |
| 1289 | + 'allpagesto', |
1289 | 1290 | 'allarticles', |
1290 | 1291 | 'allinnamespace', |
1291 | 1292 | 'allnotinnamespace', |
Index: trunk/phase3/includes/specials/SpecialAllpages.php |
— | — | @@ -13,7 +13,8 @@ |
14 | 14 | global $wgRequest, $wgOut, $wgContLang; |
15 | 15 | |
16 | 16 | # GET values |
17 | | - $from = $wgRequest->getVal( 'from' ); |
| 17 | + $from = $wgRequest->getVal( 'from', '' ); |
| 18 | + $to = $wgRequest->getVal( 'to', '' ); |
18 | 19 | $namespace = $wgRequest->getInt( 'namespace' ); |
19 | 20 | |
20 | 21 | $namespaces = $wgContLang->getNamespaces(); |
— | — | @@ -24,14 +25,8 @@ |
25 | 26 | wfMsg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) : |
26 | 27 | wfMsg( 'allarticles' ) |
27 | 28 | ); |
28 | | - |
29 | | - if ( isset($par) ) { |
30 | | - $indexPage->showChunk( $namespace, $par, $specialPage->including() ); |
31 | | - } elseif ( isset($from) ) { |
32 | | - $indexPage->showChunk( $namespace, $from, $specialPage->including() ); |
33 | | - } else { |
34 | | - $indexPage->showToplevel ( $namespace, $specialPage->including() ); |
35 | | - } |
| 29 | + |
| 30 | + $indexPage->showToplevel( $namespace, $from, $to, $specialPage->including() ); |
36 | 31 | } |
37 | 32 | |
38 | 33 | /** |
— | — | @@ -40,9 +35,14 @@ |
41 | 36 | */ |
42 | 37 | class SpecialAllpages { |
43 | 38 | /** |
44 | | - * Maximum number of pages to show on single subpage. |
| 39 | + * Maximum number of pages to show on single list subpage. |
45 | 40 | */ |
46 | | - protected $maxPerPage = 960; |
| 41 | + protected $maxPerPage = 345; |
| 42 | + |
| 43 | + /** |
| 44 | + * Maximum number of pages to show on single index subpage. |
| 45 | + */ |
| 46 | + protected $maxLineCount = 200; |
47 | 47 | |
48 | 48 | /** |
49 | 49 | * Name of this special page. Used to make title objects that reference back |
— | — | @@ -50,17 +50,13 @@ |
51 | 51 | */ |
52 | 52 | protected $name = 'Allpages'; |
53 | 53 | |
54 | | - /** |
55 | | - * Determines, which message describes the input field 'nsfrom'. |
56 | | - */ |
57 | | - protected $nsfromMsg = 'allpagesfrom'; |
58 | | - |
59 | 54 | /** |
60 | 55 | * HTML for the top form |
61 | 56 | * @param integer $namespace A namespace constant (default NS_MAIN). |
62 | | - * @param string $from Article name we are starting listing at. |
| 57 | + * @param string $from dbKey we are starting listing at. |
| 58 | + * @param string $to dbKey we are ending listing at. |
63 | 59 | */ |
64 | | -function namespaceForm ( $namespace = NS_MAIN, $from = '' ) { |
| 60 | +function namespaceForm( $namespace = NS_MAIN, $from = '', $to = '' ) { |
65 | 61 | global $wgScript; |
66 | 62 | $t = SpecialPage::getTitleFor( $this->name ); |
67 | 63 | |
— | — | @@ -72,14 +68,22 @@ |
73 | 69 | $out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) ); |
74 | 70 | $out .= "<tr> |
75 | 71 | <td class='mw-label'>" . |
76 | | - Xml::label( wfMsg( $this->nsfromMsg ), 'nsfrom' ) . |
| 72 | + Xml::label( wfMsg( 'allpagesfrom' ), 'nsfrom' ) . |
77 | 73 | "</td> |
78 | 74 | <td class='mw-input'>" . |
79 | | - Xml::input( 'from', 20, $from, array( 'id' => 'nsfrom' ) ) . |
| 75 | + Xml::input( 'from', 30, str_replace('_',' ',$from), array( 'id' => 'nsfrom' ) ) . |
80 | 76 | "</td> |
81 | 77 | </tr> |
82 | 78 | <tr> |
83 | 79 | <td class='mw-label'>" . |
| 80 | + Xml::label( wfMsg( 'allpagesto' ), 'nsto' ) . |
| 81 | + "</td> |
| 82 | + <td class='mw-input'>" . |
| 83 | + Xml::input( 'to', 30, str_replace('_',' ',$to), array( 'id' => 'nsto' ) ) . |
| 84 | + "</td> |
| 85 | + </tr> |
| 86 | + <tr> |
| 87 | + <td class='mw-label'>" . |
84 | 88 | Xml::label( wfMsg( 'namespace' ), 'namespace' ) . |
85 | 89 | "</td> |
86 | 90 | <td class='mw-input'>" . |
— | — | @@ -97,7 +101,7 @@ |
98 | 102 | /** |
99 | 103 | * @param integer $namespace (default NS_MAIN) |
100 | 104 | */ |
101 | | -function showToplevel ( $namespace = NS_MAIN, $including = false ) { |
| 105 | +function showToplevel( $namespace = NS_MAIN, $from = '', $to = '', $including = false ) { |
102 | 106 | global $wgOut, $wgContLang; |
103 | 107 | $align = $wgContLang->isRtl() ? 'left' : 'right'; |
104 | 108 | |
— | — | @@ -107,45 +111,54 @@ |
108 | 112 | $dbr = wfGetDB( DB_SLAVE ); |
109 | 113 | $out = ""; |
110 | 114 | $where = array( 'page_namespace' => $namespace ); |
| 115 | + |
| 116 | + $from = Title::makeTitleSafe( $namespace, $from ); |
| 117 | + $to = Title::makeTitleSafe( $namespace, $to ); |
| 118 | + $from = $from ? $from->getDBKey() : null; |
| 119 | + $to = $to ? $to->getDBKey() : null; |
| 120 | + |
| 121 | + if( isset($from) ) |
| 122 | + $where[] = 'page_title >= '.$dbr->addQuotes( $from ); |
| 123 | + if( isset($to) ) |
| 124 | + $where[] = 'page_title <= '.$dbr->addQuotes( $to ); |
111 | 125 | |
112 | 126 | global $wgMemc; |
113 | | - $key = wfMemcKey( 'allpages', 'ns', $namespace ); |
| 127 | + $key = wfMemcKey( 'allpages', 'ns', $namespace, $from, $to ); |
114 | 128 | $lines = $wgMemc->get( $key ); |
| 129 | + |
| 130 | + $count = $dbr->estimateRowCount( 'page', '*', $where, __METHOD__ ); |
| 131 | + $maxPerSubpage = intval($count/$this->maxLineCount); |
| 132 | + $maxPerSubpage = max($maxPerSubpage,$this->maxPerPage); |
115 | 133 | |
116 | 134 | if( !is_array( $lines ) ) { |
117 | 135 | $options = array( 'LIMIT' => 1 ); |
118 | | - if ( ! $dbr->implicitOrderby() ) { |
119 | | - $options['ORDER BY'] = 'page_title'; |
120 | | - } |
| 136 | + $options['ORDER BY'] = 'page_title ASC'; |
121 | 137 | $firstTitle = $dbr->selectField( 'page', 'page_title', $where, __METHOD__, $options ); |
122 | 138 | $lastTitle = $firstTitle; |
123 | | - |
124 | 139 | # This array is going to hold the page_titles in order. |
125 | 140 | $lines = array( $firstTitle ); |
126 | | - |
127 | 141 | # If we are going to show n rows, we need n+1 queries to find the relevant titles. |
128 | 142 | $done = false; |
129 | | - for( $i = 0; !$done; ++$i ) { |
| 143 | + while( !$done ) { |
130 | 144 | // Fetch the last title of this chunk and the first of the next |
131 | 145 | $chunk = is_null( $lastTitle ) |
132 | 146 | ? '' |
133 | 147 | : 'page_title >= ' . $dbr->addQuotes( $lastTitle ); |
134 | | - $res = $dbr->select( |
135 | | - 'page', /* FROM */ |
| 148 | + $chunk = array($chunk); |
| 149 | + $res = $dbr->select( 'page', /* FROM */ |
136 | 150 | 'page_title', /* WHAT */ |
137 | | - $where + array($chunk), |
| 151 | + array_merge($where,$chunk), |
138 | 152 | __METHOD__, |
139 | | - array ('LIMIT' => 2, 'OFFSET' => $this->maxPerPage - 1, 'ORDER BY' => 'page_title') ); |
| 153 | + array ('LIMIT' => 2, 'OFFSET' => $maxPerSubpage - 1, 'ORDER BY' => 'page_title ASC') |
| 154 | + ); |
140 | 155 | |
141 | | - if ( $s = $dbr->fetchObject( $res ) ) { |
| 156 | + if( $s = $dbr->fetchObject( $res ) ) { |
142 | 157 | array_push( $lines, $s->page_title ); |
143 | 158 | } else { |
144 | 159 | // Final chunk, but ended prematurely. Go back and find the end. |
145 | 160 | $endTitle = $dbr->selectField( 'page', 'MAX(page_title)', |
146 | | - array( |
147 | | - 'page_namespace' => $namespace, |
148 | | - $chunk |
149 | | - ), __METHOD__ ); |
| 161 | + array_merge($where,$chunk), |
| 162 | + __METHOD__ ); |
150 | 163 | array_push( $lines, $endTitle ); |
151 | 164 | $done = true; |
152 | 165 | } |
— | — | @@ -165,35 +178,35 @@ |
166 | 179 | // If there are only two or less sections, don't even display them. |
167 | 180 | // Instead, display the first section directly. |
168 | 181 | if( count( $lines ) <= 2 ) { |
169 | | - $this->showChunk( $namespace, '', $including ); |
| 182 | + $this->showChunk( $namespace, $from, $to, $including ); |
170 | 183 | return; |
171 | 184 | } |
172 | 185 | |
173 | 186 | # At this point, $lines should contain an even number of elements. |
174 | 187 | $out .= "<table class='allpageslist' style='background: inherit;'>"; |
175 | | - while ( count ( $lines ) > 0 ) { |
176 | | - $inpoint = array_shift ( $lines ); |
177 | | - $outpoint = array_shift ( $lines ); |
178 | | - $out .= $this->showline ( $inpoint, $outpoint, $namespace, false ); |
| 188 | + while( count ( $lines ) > 0 ) { |
| 189 | + $inpoint = array_shift( $lines ); |
| 190 | + $outpoint = array_shift( $lines ); |
| 191 | + $out .= $this->showline( $inpoint, $outpoint, $namespace ); |
179 | 192 | } |
180 | 193 | $out .= '</table>'; |
181 | | - $nsForm = $this->namespaceForm( $namespace, '', false ); |
| 194 | + $nsForm = $this->namespaceForm( $namespace, $from, $to ); |
182 | 195 | |
183 | 196 | # Is there more? |
184 | | - if ( $including ) { |
| 197 | + if( $including ) { |
185 | 198 | $out2 = ''; |
186 | 199 | } else { |
187 | | - $morelinks = ''; |
188 | | - if ( $morelinks != '' ) { |
| 200 | + if( isset($from) || isset($to) ) { |
| 201 | + global $wgUser; |
189 | 202 | $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">'; |
190 | 203 | $out2 .= '<tr valign="top"><td>' . $nsForm; |
191 | | - $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">'; |
192 | | - $out2 .= $morelinks . '</td></tr></table><hr />'; |
| 204 | + $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">' . |
| 205 | + $wgUser->getSkin()->makeKnownLink( $wgContLang->specialPage( "Allpages" ), wfMsgHtml ( 'allpages' ) ); |
| 206 | + $out2 .= "</td></tr></table><hr />"; |
193 | 207 | } else { |
194 | 208 | $out2 = $nsForm . '<hr />'; |
195 | 209 | } |
196 | 210 | } |
197 | | - |
198 | 211 | $wgOut->addHtml( $out2 . $out ); |
199 | 212 | } |
200 | 213 | |
— | — | @@ -207,14 +220,14 @@ |
208 | 221 | $align = $wgContLang->isRtl() ? 'left' : 'right'; |
209 | 222 | $inpointf = htmlspecialchars( str_replace( '_', ' ', $inpoint ) ); |
210 | 223 | $outpointf = htmlspecialchars( str_replace( '_', ' ', $outpoint ) ); |
211 | | - $queryparams = ($namespace ? "namespace=$namespace" : ''); |
212 | | - $special = SpecialPage::getTitleFor( $this->name, $inpoint ); |
213 | | - $link = $special->escapeLocalUrl( $queryparams ); |
| 224 | + $queryparams = $namespace ? "namespace=$namespace&" : ''; |
| 225 | + $special = SpecialPage::getTitleFor( $this->name ); |
| 226 | + $link = $special->escapeLocalUrl( $queryparams . 'from=' . urlencode($inpoint) . '&to=' . urlencode($outpoint) ); |
214 | 227 | |
215 | 228 | $out = wfMsgHtml( |
216 | 229 | 'alphaindexline', |
217 | | - "<a href=\"$link\">$inpointf</a></td><td><a href=\"$link\">", |
218 | | - "</a></td><td><a href=\"$link\">$outpointf</a>" |
| 230 | + "<a href=\"$link\">$inpointf</a></td><td>", |
| 231 | + "</td><td><a href=\"$link\">$outpointf</a>" |
219 | 232 | ); |
220 | 233 | return '<tr><td align="' . $align . '">'.$out.'</td></tr>'; |
221 | 234 | } |
— | — | @@ -223,18 +236,20 @@ |
224 | 237 | * @param integer $namespace (Default NS_MAIN) |
225 | 238 | * @param string $from list all pages from this name (default FALSE) |
226 | 239 | */ |
227 | | -function showChunk( $namespace = NS_MAIN, $from, $including = false ) { |
| 240 | +function showChunk( $namespace = NS_MAIN, $from, $to, $including = false ) { |
228 | 241 | global $wgOut, $wgUser, $wgContLang; |
229 | 242 | |
230 | 243 | $sk = $wgUser->getSkin(); |
231 | 244 | |
232 | | - $fromList = $this->getNamespaceKeyAndText($namespace, $from); |
| 245 | + $fromList = $this->getNamespaceKeyAndText( $namespace, $from ); |
| 246 | + $toList = $this->getNamespaceKeyAndText( $namespace, $to ); |
| 247 | + |
233 | 248 | $namespaces = $wgContLang->getNamespaces(); |
234 | 249 | $align = $wgContLang->isRtl() ? 'left' : 'right'; |
235 | 250 | |
236 | 251 | $n = 0; |
237 | 252 | |
238 | | - if ( !$fromList ) { |
| 253 | + if ( !$fromList || !$toList ) { |
239 | 254 | $out = wfMsgWikiHtml( 'allpagesbadtitle' ); |
240 | 255 | } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) { |
241 | 256 | // Show errormessage and reset to NS_MAIN |
— | — | @@ -242,17 +257,19 @@ |
243 | 258 | $namespace = NS_MAIN; |
244 | 259 | } else { |
245 | 260 | list( $namespace, $fromKey, $from ) = $fromList; |
| 261 | + list( $namespace, $toKey, $to ) = $toList; |
246 | 262 | |
247 | 263 | $dbr = wfGetDB( DB_SLAVE ); |
248 | 264 | $res = $dbr->select( 'page', |
249 | 265 | array( 'page_namespace', 'page_title', 'page_is_redirect' ), |
250 | 266 | array( |
251 | 267 | 'page_namespace' => $namespace, |
252 | | - 'page_title >= ' . $dbr->addQuotes( $fromKey ) |
| 268 | + 'page_title >= ' . $dbr->addQuotes( $fromKey ), |
| 269 | + 'page_title <= ' . $dbr->addQuotes( $toKey ), |
253 | 270 | ), |
254 | 271 | __METHOD__, |
255 | 272 | array( |
256 | | - 'ORDER BY' => 'page_title', |
| 273 | + 'ORDER BY' => 'page_title ASC', |
257 | 274 | 'LIMIT' => $this->maxPerPage + 1, |
258 | 275 | 'USE INDEX' => 'name_title', |
259 | 276 | ) |
— | — | @@ -291,87 +308,15 @@ |
292 | 309 | if ( $including ) { |
293 | 310 | $out2 = ''; |
294 | 311 | } else { |
295 | | - if( $from == '' ) { |
296 | | - // First chunk; no previous link. |
297 | | - $prevTitle = null; |
298 | | - } else { |
299 | | - # Get the last title from previous chunk |
300 | | - $dbr = wfGetDB( DB_SLAVE ); |
301 | | - $res_prev = $dbr->select( |
302 | | - 'page', |
303 | | - 'page_title', |
304 | | - array( 'page_namespace' => $namespace, 'page_title < '.$dbr->addQuotes($from) ), |
305 | | - __METHOD__, |
306 | | - array( 'ORDER BY' => 'page_title DESC', 'LIMIT' => $this->maxPerPage, 'OFFSET' => ($this->maxPerPage - 1 ) ) |
307 | | - ); |
308 | | - |
309 | | - # Get first title of previous complete chunk |
310 | | - if( $dbr->numrows( $res_prev ) >= $this->maxPerPage ) { |
311 | | - $pt = $dbr->fetchObject( $res_prev ); |
312 | | - $prevTitle = Title::makeTitle( $namespace, $pt->page_title ); |
313 | | - } else { |
314 | | - # The previous chunk is not complete, need to link to the very first title |
315 | | - # available in the database |
316 | | - $options = array( 'LIMIT' => 1 ); |
317 | | - if ( ! $dbr->implicitOrderby() ) { |
318 | | - $options['ORDER BY'] = 'page_title'; |
319 | | - } |
320 | | - $reallyFirstPage_title = $dbr->selectField( 'page', 'page_title', array( 'page_namespace' => $namespace ), __METHOD__, $options ); |
321 | | - # Show the previous link if it s not the current requested chunk |
322 | | - if( $from != $reallyFirstPage_title ) { |
323 | | - $prevTitle = Title::makeTitle( $namespace, $reallyFirstPage_title ); |
324 | | - } else { |
325 | | - $prevTitle = null; |
326 | | - } |
327 | | - } |
328 | | - } |
329 | | - |
330 | | - $nsForm = $this->namespaceForm( $namespace, $from ); |
| 312 | + $nsForm = $this->namespaceForm( $namespace, $from, $to ); |
331 | 313 | $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">'; |
332 | 314 | $out2 .= '<tr valign="top"><td>' . $nsForm; |
333 | 315 | $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">' . |
334 | | - $sk->makeKnownLink( $wgContLang->specialPage( "Allpages" ), |
335 | | - wfMsgHtml ( 'allpages' ) ); |
336 | | - |
337 | | - $self = SpecialPage::getTitleFor( 'Allpages' ); |
338 | | - |
339 | | - # Do we put a previous link ? |
340 | | - if( isset( $prevTitle ) && $pt = $prevTitle->getText() ) { |
341 | | - $q = 'from=' . $prevTitle->getPartialUrl() |
342 | | - . ( $namespace ? '&namespace=' . $namespace : '' ); |
343 | | - $prevLink = $sk->makeKnownLinkObj( $self, |
344 | | - wfMsgHTML( 'prevpage', htmlspecialchars( $pt ) ), $q ); |
345 | | - $out2 .= ' | ' . $prevLink; |
346 | | - } |
347 | | - |
348 | | - if( $n == $this->maxPerPage && $s = $dbr->fetchObject($res) ) { |
349 | | - # $s is the first link of the next chunk |
350 | | - $t = Title::MakeTitle($namespace, $s->page_title); |
351 | | - $q = 'from=' . $t->getPartialUrl() |
352 | | - . ( $namespace ? '&namespace=' . $namespace : '' ); |
353 | | - $nextLink = $sk->makeKnownLinkObj( $self, |
354 | | - wfMsgHtml( 'nextpage', htmlspecialchars( $t->getText() ) ), $q ); |
355 | | - $out2 .= ' | ' . $nextLink; |
356 | | - } |
| 316 | + $sk->makeKnownLink( $wgContLang->specialPage( "Allpages" ), wfMsgHtml ( 'allpages' ) ); |
357 | 317 | $out2 .= "</td></tr></table><hr />"; |
358 | 318 | } |
359 | 319 | |
360 | 320 | $wgOut->addHtml( $out2 . $out ); |
361 | | - if( isset($prevLink) or isset($nextLink) ) { |
362 | | - $wgOut->addHtml( '<hr /><p style="font-size: smaller; float: ' . $align . '">' ); |
363 | | - if( isset( $prevLink ) ) { |
364 | | - $wgOut->addHTML( $prevLink ); |
365 | | - } |
366 | | - if( isset( $prevLink ) && isset( $nextLink ) ) { |
367 | | - $wgOut->addHTML( ' | ' ); |
368 | | - } |
369 | | - if( isset( $nextLink ) ) { |
370 | | - $wgOut->addHTML( $nextLink ); |
371 | | - } |
372 | | - $wgOut->addHTML( '</p>' ); |
373 | | - |
374 | | - } |
375 | | - |
376 | 321 | } |
377 | 322 | |
378 | 323 | /** |
— | — | @@ -381,7 +326,7 @@ |
382 | 327 | * @static (sort of) |
383 | 328 | * @access private |
384 | 329 | */ |
385 | | -function getNamespaceKeyAndText ($ns, $text) { |
| 330 | +function getNamespaceKeyAndText( $ns, $text ) { |
386 | 331 | if ( $text == '' ) |
387 | 332 | return array( $ns, '', '' ); # shortcut for common case |
388 | 333 | |
— | — | @@ -401,4 +346,5 @@ |
402 | 347 | return NULL; |
403 | 348 | } |
404 | 349 | } |
| 350 | + |
405 | 351 | } |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -2004,6 +2004,7 @@ |
2005 | 2005 | 'nextpage' => 'Next page ($1)', |
2006 | 2006 | 'prevpage' => 'Previous page ($1)', |
2007 | 2007 | 'allpagesfrom' => 'Display pages starting at:', |
| 2008 | +'allpagesto' => 'Display pages ending at:', |
2008 | 2009 | 'allarticles' => 'All pages', |
2009 | 2010 | 'allinnamespace' => 'All pages ($1 namespace)', |
2010 | 2011 | 'allnotinnamespace' => 'All pages (not in $1 namespace)', |