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', null ); |
| 18 | + $to = $wgRequest->getVal( 'to', null ); |
18 | 19 | $namespace = $wgRequest->getInt( 'namespace' ); |
19 | 20 | |
20 | 21 | $namespaces = $wgContLang->getNamespaces(); |
— | — | @@ -23,14 +24,14 @@ |
24 | 25 | $wgOut->setPagetitle( ( $namespace > 0 && in_array( $namespace, array_keys( $namespaces) ) ) ? |
25 | 26 | wfMsg( 'allinnamespace', str_replace( '_', ' ', $namespaces[$namespace] ) ) : |
26 | 27 | wfMsg( 'allarticles' ) |
27 | | - ); |
| 28 | + ); |
28 | 29 | |
29 | | - if ( isset($par) ) { |
30 | | - $indexPage->showChunk( $namespace, $par, $specialPage->including() ); |
31 | | - } elseif ( isset($from) ) { |
32 | | - $indexPage->showChunk( $namespace, $from, $specialPage->including() ); |
| 30 | + if( isset($par) ) { |
| 31 | + $indexPage->showChunk( $namespace, $par, $to, $specialPage->including() ); |
| 32 | + } elseif( isset($from) && !isset($to) ) { |
| 33 | + $indexPage->showChunk( $namespace, $from, $to, $specialPage->including() ); |
33 | 34 | } else { |
34 | | - $indexPage->showToplevel ( $namespace, $specialPage->including() ); |
| 35 | + $indexPage->showToplevel( $namespace, $from, $to, $specialPage->including() ); |
35 | 36 | } |
36 | 37 | } |
37 | 38 | |
— | — | @@ -42,8 +43,18 @@ |
43 | 44 | /** |
44 | 45 | * Maximum number of pages to show on single subpage. |
45 | 46 | */ |
46 | | - protected $maxPerPage = 960; |
| 47 | + protected $maxPerPage = 345; |
47 | 48 | |
| 49 | + /** |
| 50 | + * Maximum number of pages to show on single index subpage. |
| 51 | + */ |
| 52 | + protected $maxLineCount = 200; |
| 53 | + |
| 54 | + /** |
| 55 | + * Maximum number of chars to show for an entry. |
| 56 | + */ |
| 57 | + protected $maxPageLength = 70; |
| 58 | + |
48 | 59 | /** |
49 | 60 | * Name of this special page. Used to make title objects that reference back |
50 | 61 | * to this page. |
— | — | @@ -58,46 +69,55 @@ |
59 | 70 | /** |
60 | 71 | * HTML for the top form |
61 | 72 | * @param integer $namespace A namespace constant (default NS_MAIN). |
62 | | - * @param string $from Article name we are starting listing at. |
| 73 | + * @param string $from dbKey we are starting listing at. |
| 74 | + * @param string $to dbKey we are ending listing at. |
63 | 75 | */ |
64 | | -function namespaceForm ( $namespace = NS_MAIN, $from = '' ) { |
65 | | - global $wgScript; |
66 | | - $t = SpecialPage::getTitleFor( $this->name ); |
| 76 | +function namespaceForm( $namespace = NS_MAIN, $from = '', $to = '' ) { |
| 77 | + global $wgScript; |
| 78 | + $t = SpecialPage::getTitleFor( $this->name ); |
67 | 79 | |
68 | | - $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) ); |
69 | | - $out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); |
70 | | - $out .= Xml::hidden( 'title', $t->getPrefixedText() ); |
71 | | - $out .= Xml::openElement( 'fieldset' ); |
72 | | - $out .= Xml::element( 'legend', null, wfMsg( 'allpages' ) ); |
73 | | - $out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) ); |
74 | | - $out .= "<tr> |
75 | | - <td class='mw-label'>" . |
76 | | - Xml::label( wfMsg( $this->nsfromMsg ), 'nsfrom' ) . |
77 | | - "</td> |
78 | | - <td class='mw-input'>" . |
79 | | - Xml::input( 'from', 20, $from, array( 'id' => 'nsfrom' ) ) . |
80 | | - "</td> |
81 | | - </tr> |
82 | | - <tr> |
83 | | - <td class='mw-label'>" . |
84 | | - Xml::label( wfMsg( 'namespace' ), 'namespace' ) . |
85 | | - "</td> |
86 | | - <td class='mw-input'>" . |
87 | | - Xml::namespaceSelector( $namespace, null ) . ' ' . |
88 | | - Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . |
89 | | - "</td> |
90 | | - </tr>"; |
91 | | - $out .= Xml::closeElement( 'table' ); |
92 | | - $out .= Xml::closeElement( 'fieldset' ); |
93 | | - $out .= Xml::closeElement( 'form' ); |
94 | | - $out .= Xml::closeElement( 'div' ); |
95 | | - return $out; |
| 80 | + $out = Xml::openElement( 'div', array( 'class' => 'namespaceoptions' ) ); |
| 81 | + $out .= Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); |
| 82 | + $out .= Xml::hidden( 'title', $t->getPrefixedText() ); |
| 83 | + $out .= Xml::openElement( 'fieldset' ); |
| 84 | + $out .= Xml::element( 'legend', null, wfMsg( 'allpages' ) ); |
| 85 | + $out .= Xml::openElement( 'table', array( 'id' => 'nsselect', 'class' => 'allpages' ) ); |
| 86 | + $out .= "<tr> |
| 87 | + <td class='mw-label'>" . |
| 88 | + Xml::label( wfMsg( 'allpagesfrom' ), 'nsfrom' ) . |
| 89 | + "</td> |
| 90 | + <td class='mw-input'>" . |
| 91 | + Xml::input( 'from', 30, str_replace('_',' ',$from), array( 'id' => 'nsfrom' ) ) . |
| 92 | + "</td> |
| 93 | + </tr> |
| 94 | + <tr> |
| 95 | + <td class='mw-label'>" . |
| 96 | + Xml::label( wfMsg( 'allpagesto' ), 'nsto' ) . |
| 97 | + "</td> |
| 98 | + <td class='mw-input'>" . |
| 99 | + Xml::input( 'to', 30, str_replace('_',' ',$to), array( 'id' => 'nsto' ) ) . |
| 100 | + "</td> |
| 101 | + </tr> |
| 102 | + <tr> |
| 103 | + <td class='mw-label'>" . |
| 104 | + Xml::label( wfMsg( 'namespace' ), 'namespace' ) . |
| 105 | + "</td> |
| 106 | + <td class='mw-input'>" . |
| 107 | + Xml::namespaceSelector( $namespace, null ) . ' ' . |
| 108 | + Xml::submitButton( wfMsg( 'allpagessubmit' ) ) . |
| 109 | + "</td> |
| 110 | + </tr>"; |
| 111 | + $out .= Xml::closeElement( 'table' ); |
| 112 | + $out .= Xml::closeElement( 'fieldset' ); |
| 113 | + $out .= Xml::closeElement( 'form' ); |
| 114 | + $out .= Xml::closeElement( 'div' ); |
| 115 | + return $out; |
96 | 116 | } |
97 | 117 | |
98 | 118 | /** |
99 | 119 | * @param integer $namespace (default NS_MAIN) |
100 | 120 | */ |
101 | | -function showToplevel ( $namespace = NS_MAIN, $including = false ) { |
| 121 | +function showToplevel( $namespace = NS_MAIN, $from = '', $to = '', $including = false ) { |
102 | 122 | global $wgOut, $wgContLang; |
103 | 123 | $align = $wgContLang->isRtl() ? 'left' : 'right'; |
104 | 124 | |
— | — | @@ -107,45 +127,54 @@ |
108 | 128 | $dbr = wfGetDB( DB_SLAVE ); |
109 | 129 | $out = ""; |
110 | 130 | $where = array( 'page_namespace' => $namespace ); |
| 131 | + |
| 132 | + $from = Title::makeTitleSafe( $namespace, $from ); |
| 133 | + $to = Title::makeTitleSafe( $namespace, $to ); |
| 134 | + $from = ( $from && $from->isLocal() ) ? $from->getDBKey() : null; |
| 135 | + $to = ( $to && $to->isLocal() ) ? $to->getDBKey() : null; |
| 136 | + |
| 137 | + if( isset($from) ) |
| 138 | + $where[] = 'page_title >= '.$dbr->addQuotes( $from ); |
| 139 | + if( isset($to) ) |
| 140 | + $where[] = 'page_title <= '.$dbr->addQuotes( $to ); |
111 | 141 | |
112 | 142 | global $wgMemc; |
113 | | - $key = wfMemcKey( 'allpages', 'ns', $namespace ); |
| 143 | + $key = wfMemcKey( 'allpages', 'ns', $namespace, $from, $to ); |
114 | 144 | $lines = $wgMemc->get( $key ); |
| 145 | + |
| 146 | + $count = $dbr->estimateRowCount( 'page', '*', $where, __METHOD__ ); |
| 147 | + $maxPerSubpage = intval($count/$this->maxLineCount); |
| 148 | + $maxPerSubpage = max($maxPerSubpage,$this->maxPerPage); |
115 | 149 | |
116 | 150 | if( !is_array( $lines ) ) { |
117 | 151 | $options = array( 'LIMIT' => 1 ); |
118 | | - if ( ! $dbr->implicitOrderby() ) { |
119 | | - $options['ORDER BY'] = 'page_title'; |
120 | | - } |
| 152 | + $options['ORDER BY'] = 'page_title ASC'; |
121 | 153 | $firstTitle = $dbr->selectField( 'page', 'page_title', $where, __METHOD__, $options ); |
122 | 154 | $lastTitle = $firstTitle; |
123 | | - |
124 | 155 | # This array is going to hold the page_titles in order. |
125 | 156 | $lines = array( $firstTitle ); |
126 | | - |
127 | 157 | # If we are going to show n rows, we need n+1 queries to find the relevant titles. |
128 | 158 | $done = false; |
129 | | - for( $i = 0; !$done; ++$i ) { |
| 159 | + while( !$done ) { |
130 | 160 | // Fetch the last title of this chunk and the first of the next |
131 | 161 | $chunk = is_null( $lastTitle ) |
132 | 162 | ? '' |
133 | 163 | : 'page_title >= ' . $dbr->addQuotes( $lastTitle ); |
134 | | - $res = $dbr->select( |
135 | | - 'page', /* FROM */ |
| 164 | + $chunk = array($chunk); |
| 165 | + $res = $dbr->select( 'page', /* FROM */ |
136 | 166 | 'page_title', /* WHAT */ |
137 | | - $where + array($chunk), |
| 167 | + array_merge($where,$chunk), |
138 | 168 | __METHOD__, |
139 | | - array ('LIMIT' => 2, 'OFFSET' => $this->maxPerPage - 1, 'ORDER BY' => 'page_title') ); |
| 169 | + array ('LIMIT' => 2, 'OFFSET' => $maxPerSubpage - 1, 'ORDER BY' => 'page_title ASC') |
| 170 | + ); |
140 | 171 | |
141 | | - if ( $s = $dbr->fetchObject( $res ) ) { |
| 172 | + if( $s = $dbr->fetchObject( $res ) ) { |
142 | 173 | array_push( $lines, $s->page_title ); |
143 | 174 | } else { |
144 | 175 | // Final chunk, but ended prematurely. Go back and find the end. |
145 | 176 | $endTitle = $dbr->selectField( 'page', 'MAX(page_title)', |
146 | | - array( |
147 | | - 'page_namespace' => $namespace, |
148 | | - $chunk |
149 | | - ), __METHOD__ ); |
| 177 | + array_merge($where,$chunk), |
| 178 | + __METHOD__ ); |
150 | 179 | array_push( $lines, $endTitle ); |
151 | 180 | $done = true; |
152 | 181 | } |
— | — | @@ -165,35 +194,39 @@ |
166 | 195 | // If there are only two or less sections, don't even display them. |
167 | 196 | // Instead, display the first section directly. |
168 | 197 | if( count( $lines ) <= 2 ) { |
169 | | - $this->showChunk( $namespace, '', $including ); |
| 198 | + if( !empty($lines) ) { |
| 199 | + $this->showChunk( $namespace, $lines[0], $lines[count($lines)-1], $including ); |
| 200 | + } else { |
| 201 | + $wgOut->addHtml( $this->namespaceForm( $namespace, $from, $to ) ); |
| 202 | + } |
170 | 203 | return; |
171 | 204 | } |
172 | 205 | |
173 | 206 | # At this point, $lines should contain an even number of elements. |
174 | 207 | $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 ); |
| 208 | + while( count ( $lines ) > 0 ) { |
| 209 | + $inpoint = array_shift( $lines ); |
| 210 | + $outpoint = array_shift( $lines ); |
| 211 | + $out .= $this->showline( $inpoint, $outpoint, $namespace ); |
179 | 212 | } |
180 | 213 | $out .= '</table>'; |
181 | | - $nsForm = $this->namespaceForm( $namespace, '', false ); |
| 214 | + $nsForm = $this->namespaceForm( $namespace, $from, $to ); |
182 | 215 | |
183 | 216 | # Is there more? |
184 | | - if ( $including ) { |
| 217 | + if( $including ) { |
185 | 218 | $out2 = ''; |
186 | 219 | } else { |
187 | | - $morelinks = ''; |
188 | | - if ( $morelinks != '' ) { |
| 220 | + if( isset($from) || isset($to) ) { |
| 221 | + global $wgUser; |
189 | 222 | $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">'; |
190 | 223 | $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 />'; |
| 224 | + $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">' . |
| 225 | + $wgUser->getSkin()->makeKnownLink( $wgContLang->specialPage( "Allpages" ), wfMsgHtml ( 'allpages' ) ); |
| 226 | + $out2 .= "</td></tr></table><hr />"; |
193 | 227 | } else { |
194 | 228 | $out2 = $nsForm . '<hr />'; |
195 | 229 | } |
196 | 230 | } |
197 | | - |
198 | 231 | $wgOut->addHtml( $out2 . $out ); |
199 | 232 | } |
200 | 233 | |
— | — | @@ -207,14 +240,17 @@ |
208 | 241 | $align = $wgContLang->isRtl() ? 'left' : 'right'; |
209 | 242 | $inpointf = htmlspecialchars( str_replace( '_', ' ', $inpoint ) ); |
210 | 243 | $outpointf = htmlspecialchars( str_replace( '_', ' ', $outpoint ) ); |
211 | | - $queryparams = ($namespace ? "namespace=$namespace" : ''); |
212 | | - $special = SpecialPage::getTitleFor( $this->name, $inpoint ); |
213 | | - $link = $special->escapeLocalUrl( $queryparams ); |
| 244 | + // Don't let the length runaway |
| 245 | + $inpointf = $wgContLang->truncate( $inpointf, $this->maxPageLength, '...' ); |
| 246 | + $outpointf = $wgContLang->truncate( $outpointf, $this->maxPageLength, '...' ); |
214 | 247 | |
215 | | - $out = wfMsgHtml( |
216 | | - 'alphaindexline', |
217 | | - "<a href=\"$link\">$inpointf</a></td><td><a href=\"$link\">", |
218 | | - "</a></td><td><a href=\"$link\">$outpointf</a>" |
| 248 | + $queryparams = $namespace ? "namespace=$namespace&" : ''; |
| 249 | + $special = SpecialPage::getTitleFor( $this->name ); |
| 250 | + $link = $special->escapeLocalUrl( $queryparams . 'from=' . urlencode($inpoint) . '&to=' . urlencode($outpoint) ); |
| 251 | + |
| 252 | + $out = wfMsgHtml( 'alphaindexline', |
| 253 | + "<a href=\"$link\">$inpointf</a></td><td>", |
| 254 | + "</td><td><a href=\"$link\">$outpointf</a>" |
219 | 255 | ); |
220 | 256 | return '<tr><td align="' . $align . '">'.$out.'</td></tr>'; |
221 | 257 | } |
— | — | @@ -222,19 +258,21 @@ |
223 | 259 | /** |
224 | 260 | * @param integer $namespace (Default NS_MAIN) |
225 | 261 | * @param string $from list all pages from this name (default FALSE) |
| 262 | + * @param string $to list all pages to this name (default FALSE) |
226 | 263 | */ |
227 | | -function showChunk( $namespace = NS_MAIN, $from, $including = false ) { |
| 264 | +function showChunk( $namespace = NS_MAIN, $from = false, $to = false, $including = false ) { |
228 | 265 | global $wgOut, $wgUser, $wgContLang; |
229 | 266 | |
230 | 267 | $sk = $wgUser->getSkin(); |
231 | 268 | |
232 | 269 | $fromList = $this->getNamespaceKeyAndText($namespace, $from); |
| 270 | + $toList = $this->getNamespaceKeyAndText( $namespace, $to ); |
233 | 271 | $namespaces = $wgContLang->getNamespaces(); |
234 | 272 | $align = $wgContLang->isRtl() ? 'left' : 'right'; |
235 | 273 | |
236 | 274 | $n = 0; |
237 | 275 | |
238 | | - if ( !$fromList ) { |
| 276 | + if ( !$fromList || !$toList ) { |
239 | 277 | $out = wfMsgWikiHtml( 'allpagesbadtitle' ); |
240 | 278 | } elseif ( !in_array( $namespace, array_keys( $namespaces ) ) ) { |
241 | 279 | // Show errormessage and reset to NS_MAIN |
— | — | @@ -242,14 +280,20 @@ |
243 | 281 | $namespace = NS_MAIN; |
244 | 282 | } else { |
245 | 283 | list( $namespace, $fromKey, $from ) = $fromList; |
| 284 | + list( $namespace, $toKey, $to ) = $toList; |
246 | 285 | |
247 | 286 | $dbr = wfGetDB( DB_SLAVE ); |
| 287 | + $conds = array( |
| 288 | + 'page_namespace' => $namespace, |
| 289 | + 'page_title >= ' . $dbr->addQuotes( $fromKey ) |
| 290 | + ); |
| 291 | + if( $toKey !== "" ) { |
| 292 | + $conds[] = 'page_title <= ' . $dbr->addQuotes( $toKey ); |
| 293 | + } |
| 294 | + |
248 | 295 | $res = $dbr->select( 'page', |
249 | 296 | array( 'page_namespace', 'page_title', 'page_is_redirect' ), |
250 | | - array( |
251 | | - 'page_namespace' => $namespace, |
252 | | - 'page_title >= ' . $dbr->addQuotes( $fromKey ) |
253 | | - ), |
| 297 | + $conds, |
254 | 298 | __METHOD__, |
255 | 299 | array( |
256 | 300 | 'ORDER BY' => 'page_title', |
— | — | @@ -316,7 +360,8 @@ |
317 | 361 | if ( ! $dbr->implicitOrderby() ) { |
318 | 362 | $options['ORDER BY'] = 'page_title'; |
319 | 363 | } |
320 | | - $reallyFirstPage_title = $dbr->selectField( 'page', 'page_title', array( 'page_namespace' => $namespace ), __METHOD__, $options ); |
| 364 | + $reallyFirstPage_title = $dbr->selectField( 'page', 'page_title', |
| 365 | + array( 'page_namespace' => $namespace ), __METHOD__, $options ); |
321 | 366 | # Show the previous link if it s not the current requested chunk |
322 | 367 | if( $from != $reallyFirstPage_title ) { |
323 | 368 | $prevTitle = Title::makeTitle( $namespace, $reallyFirstPage_title ); |
— | — | @@ -326,7 +371,7 @@ |
327 | 372 | } |
328 | 373 | } |
329 | 374 | |
330 | | - $nsForm = $this->namespaceForm( $namespace, $from ); |
| 375 | + $nsForm = $this->namespaceForm( $namespace, $from, $to ); |
331 | 376 | $out2 = '<table style="background: inherit;" width="100%" cellpadding="0" cellspacing="0" border="0">'; |
332 | 377 | $out2 .= '<tr valign="top"><td>' . $nsForm; |
333 | 378 | $out2 .= '</td><td align="' . $align . '" style="font-size: smaller; margin-bottom: 1em;">' . |
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)', |