r69972 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r69971‎ | r69972 | r69973 >
Date:21:27, 26 July 2010
Author:simetrical
Status:ok
Tags:
Comment:
Paginate the three category sections separately

This fully fixes bug 1211. It might be buggy, and
$wgExperimentalCategorySort sure makes it hackish. I should definitely
have gone with some kind of branch here. More testing would be good.
Also, the UI could use improvement (extra ugly next/previous 200 links
in various places).
Modified paths:
  • /trunk/phase3/includes/CategoryPage.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/CategoryPage.php
@@ -51,11 +51,20 @@
5252 }
5353
5454 function closeShowCategory() {
55 - global $wgOut, $wgRequest;
56 - $from = $wgRequest->getVal( 'from' );
57 - $until = $wgRequest->getVal( 'until' );
 55+ global $wgOut, $wgRequest, $wgExperimentalCategorySort;
5856
59 - $viewer = new CategoryViewer( $this->mTitle, $from, $until );
 57+ if ( $wgExperimentalCategorySort ) {
 58+ $from = $until = array();
 59+ foreach ( array( 'page', 'subcat', 'file' ) as $type ) {
 60+ $from[$type] = $wgRequest->getVal( "{$type}from" );
 61+ $until[$type] = $wgRequest->getVal( "{$type}until" );
 62+ }
 63+ } else {
 64+ $from = $wgRequest->getVal( 'from' );
 65+ $until = $wgRequest->getVal( 'until' );
 66+ }
 67+
 68+ $viewer = new CategoryViewer( $this->mTitle, $from, $until, $wgRequest->getValues() );
6069 $wgOut->addHTML( $viewer->getHTML() );
6170 }
6271 }
@@ -66,16 +75,19 @@
6776 $children, $children_start_char,
6877 $showGallery, $gallery,
6978 $skin;
70 - /** Category object for this page */
 79+ # Category object for this page
7180 private $cat;
 81+ # The original query array, to be used in generating paging links.
 82+ private $query;
7283
73 - function __construct( $title, $from = '', $until = '' ) {
 84+ function __construct( $title, $from = '', $until = '', $query = array() ) {
7485 global $wgCategoryPagingLimit;
7586 $this->title = $title;
7687 $this->from = $from;
7788 $this->until = $until;
7889 $this->limit = $wgCategoryPagingLimit;
7990 $this->cat = Category::newFromTitle( $title );
 91+ $this->query = $query;
8092 }
8193
8294 /**
@@ -194,7 +206,13 @@
195207 */
196208 function addImage( Title $title, $sortkey, $pageLength, $isRedirect = false ) {
197209 if ( $this->showGallery ) {
198 - if ( $this->flip ) {
 210+ global $wgExperimentalCategorySort;
 211+ if ( $wgExperimentalCategorySort ) {
 212+ $flip = $this->flip['file'];
 213+ } else {
 214+ $flip = $this->flip;
 215+ }
 216+ if ( $flip ) {
199217 $this->gallery->insert( $title );
200218 } else {
201219 $this->gallery->add( $title );
@@ -228,66 +246,81 @@
229247 }
230248
231249 function finaliseCategoryState() {
232 - if ( $this->flip ) {
 250+ global $wgExperimentalCategorySort;
 251+ if ( ( !$wgExperimentalCategorySort && $this->flip )
 252+ || ( $wgExperimentalCategorySort && $this->flip['subcat'] ) ) {
233253 $this->children = array_reverse( $this->children );
234254 $this->children_start_char = array_reverse( $this->children_start_char );
 255+ }
 256+ if ( ( !$wgExperimentalCategorySort && $this->flip )
 257+ || ( $wgExperimentalCategorySort && $this->flip['page'] ) ) {
235258 $this->articles = array_reverse( $this->articles );
236259 $this->articles_start_char = array_reverse( $this->articles_start_char );
237260 }
238261 }
239262
240263 function doCategoryQuery() {
241 - global $wgExperimentalCategorySort;
 264+ global $wgExperimentalCategorySort, $wgRequest, $wgContLang;
242265
243266 $dbr = wfGetDB( DB_SLAVE, 'category' );
244 - if ( $this->from != '' ) {
245 - $pageCondition = 'cl_sortkey >= ' . $dbr->addQuotes( $this->from );
246 - $this->flip = false;
247 - } elseif ( $this->until != '' ) {
248 - $pageCondition = 'cl_sortkey < ' . $dbr->addQuotes( $this->until );
249 - $this->flip = true;
250 - } else {
251 - $pageCondition = '1 = 1';
252 - $this->flip = false;
253 - }
254267
255268 $tables = array( 'page', 'categorylinks', 'category' );
256269 $fields = array( 'page_title', 'page_namespace', 'page_len',
257270 'page_is_redirect', 'cl_sortkey', 'cat_id', 'cat_title',
258271 'cat_subcats', 'cat_pages', 'cat_files' );
259272 $conds = array( 'cl_to' => $this->title->getDBkey() );
260 - $opts = array( 'ORDER BY' => $this->flip ? 'cl_sortkey DESC' :
261 - 'cl_sortkey', 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ) );
 273+ $opts = array(
 274+ 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ),
 275+ 'LIMIT' => $this->limit + 1,
 276+ );
262277 $joins = array( 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
263278 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY ) );
264279
265280 if ( $wgExperimentalCategorySort ) {
266281 # Copy-pasted from below, but that's okay, because the stuff below
267282 # will be deleted when this becomes the default.
268 - $count = 0;
269 - $this->nextPage = null;
 283+ $this->nextPage = array(
 284+ 'page' => null,
 285+ 'subcat' => null,
 286+ 'file' => null,
 287+ );
 288+ $this->flip = array( 'page' => false, 'subcat' => false, 'file' => false );
270289
271290 foreach ( array( 'page', 'subcat', 'file' ) as $type ) {
 291+ # Get the sortkeys for start/end, if applicable. Note that if
 292+ # the collation in the database differs from the one
 293+ # $wgContLang is using, pagination might go totally haywire.
 294+ $extraConds = array( 'cl_type' => $type );
 295+ if ( $this->from[$type] !== null ) {
 296+ $extraConds[] = 'cl_sortkey >= '
 297+ . $dbr->addQuotes( $wgContLang->convertToSortkey( $this->from[$type] ) );
 298+ } elseif ( $this->until[$type] !== null ) {
 299+ $extraConds[] = 'cl_sortkey < '
 300+ . $dbr->addQuotes( $wgContLang->convertToSortkey( $this->until[$type] ) );
 301+ $this->flip[$type] = true;
 302+ }
 303+
272304 $res = $dbr->select(
273305 $tables,
274306 array_merge( $fields, array( 'cl_sortkey_prefix' ) ),
275 - $conds + array( 'cl_type' => $type ) + ( $type == 'page' ? array( $pageCondition ) : array() ),
 307+ $conds + $extraConds,
276308 __METHOD__,
277 - $opts + ( $type == 'page' ? array( 'LIMIT' => $this->limit + 1 ) : array() ),
 309+ $opts + array( 'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey' ),
278310 $joins
279311 );
280312
 313+ $count = 0;
281314 foreach ( $res as $row ) {
282 - if ( $type == 'page' && ++$count > $this->limit ) {
 315+ $title = Title::newFromRow( $row );
 316+ $rawSortkey = $row->cl_sortkey_prefix . $title->getCategorySortkey();
 317+
 318+ if ( ++$count > $this->limit ) {
283319 # We've reached the one extra which shows that there
284320 # are additional pages to be had. Stop here...
285 - $this->nextPage = $row->cl_sortkey;
 321+ $this->nextPage[$type] = $rawSortkey;
286322 break;
287323 }
288324
289 - $title = Title::newFromRow( $row );
290 - $rawSortkey = $row->cl_sortkey_prefix . $title->getCategorySortkey();
291 -
292325 if ( $title->getNamespace() == NS_CATEGORY ) {
293326 $cat = Category::newFromRow( $row, $title );
294327 $this->addSubcategoryObject( $cat, $rawSortkey, $row->page_len );
@@ -304,12 +337,23 @@
305338
306339 # Non-$wgExperimentalCategorySort stuff
307340
 341+ if ( $this->from != '' ) {
 342+ $pageCondition = 'cl_sortkey >= ' . $dbr->addQuotes( $this->from );
 343+ $this->flip = false;
 344+ } elseif ( $this->until != '' ) {
 345+ $pageCondition = 'cl_sortkey < ' . $dbr->addQuotes( $this->until );
 346+ $this->flip = true;
 347+ } else {
 348+ $pageCondition = '1 = 1';
 349+ $this->flip = false;
 350+ }
 351+
308352 $res = $dbr->select(
309353 $tables,
310354 $fields,
311355 $conds + array( $pageCondition ),
312356 __METHOD__,
313 - $opts + array( 'LIMIT' => $this->limit + 1 ),
 357+ $opts + array( 'ORDER BY' => $this->flip ? 'cl_sortkey DESC' : 'cl_sortkey' ),
314358 $joins
315359 );
316360
@@ -356,7 +400,9 @@
357401 $r .= "<div id=\"mw-subcategories\">\n";
358402 $r .= '<h2>' . wfMsg( 'subcategories' ) . "</h2>\n";
359403 $r .= $countmsg;
 404+ $r .= $this->getSectionPagingLinks( 'subcat' );
360405 $r .= $this->formatList( $this->children, $this->children_start_char );
 406+ $r .= $this->getSectionPagingLinks( 'subcat' );
361407 $r .= "\n</div>";
362408 }
363409 return $r;
@@ -380,31 +426,63 @@
381427 $r = "<div id=\"mw-pages\">\n";
382428 $r .= '<h2>' . wfMsg( 'category_header', $ti ) . "</h2>\n";
383429 $r .= $countmsg;
 430+ $r .= $this->getSectionPagingLinks( 'page' );
384431 $r .= $this->formatList( $this->articles, $this->articles_start_char );
 432+ $r .= $this->getSectionPagingLinks( 'page' );
385433 $r .= "\n</div>";
386434 }
387435 return $r;
388436 }
389437
390438 function getImageSection() {
 439+ $r = '';
391440 if ( $this->showGallery && ! $this->gallery->isEmpty() ) {
392441 $dbcnt = $this->cat->getFileCount();
393442 $rescnt = $this->gallery->count();
394443 $countmsg = $this->getCountMessage( $rescnt, $dbcnt, 'file' );
395444
396 - return "<div id=\"mw-category-media\">\n" .
397 - '<h2>' . wfMsg( 'category-media-header', htmlspecialchars( $this->title->getText() ) ) . "</h2>\n" .
398 - $countmsg . $this->gallery->toHTML() . "\n</div>";
 445+ $r .= "<div id=\"mw-category-media\">\n";
 446+ $r .= '<h2>' . wfMsg( 'category-media-header', htmlspecialchars( $this->title->getText() ) ) . "</h2>\n";
 447+ $r .= $countmsg;
 448+ $r .= $this->getSectionPagingLinks( 'file' );
 449+ $r .= $this->gallery->toHTML();
 450+ $r .= $this->getSectionPagingLinks( 'file' );
 451+ $r .= "\n</div>";
 452+ }
 453+ return $r;
 454+ }
 455+
 456+ /**
 457+ * Get the paging links for a section (subcats/pages/files), to go at the top and bottom
 458+ * of the output.
 459+ *
 460+ * @param string $type 'page', 'subcat', or 'file'
 461+ * @return string HTML output, possibly empty if there are no other pages
 462+ */
 463+ private function getSectionPagingLinks( $type ) {
 464+ global $wgExperimentalCategorySort;
 465+ if ( !$wgExperimentalCategorySort ) {
 466+ return '';
 467+ }
 468+ if ( $this->until[$type] !== null ) {
 469+ return $this->pagingLinks( $this->nextPage[$type], $this->until[$type], $type );
 470+ } elseif ( $this->nextPage[$type] !== null || $this->from[$type] !== null ) {
 471+ return $this->pagingLinks( $this->from[$type], $this->nextPage[$type], $type );
399472 } else {
400473 return '';
401474 }
402475 }
403476
404477 function getCategoryBottom() {
 478+ global $wgExperimentalCategorySort;
 479+ if ( $wgExperimentalCategorySort ) {
 480+ # We have per-section paging links, no global ones.
 481+ return '';
 482+ }
405483 if ( $this->until != '' ) {
406 - return $this->pagingLinks( $this->title, $this->nextPage, $this->until, $this->limit );
 484+ return $this->pagingLinks( $this->nextPage, $this->until );
407485 } elseif ( $this->nextPage != '' || $this->from != '' ) {
408 - return $this->pagingLinks( $this->title, $this->from, $this->nextPage, $this->limit );
 486+ return $this->pagingLinks( $this->from, $this->nextPage );
409487 } else {
410488 return '';
411489 }
@@ -514,26 +592,27 @@
515593 }
516594
517595 /**
518 - * @param $title Title object
519 - * @param $first String
520 - * @param $last String
521 - * @param $limit Int
522 - * @param $query Array: additional query options to pass
523 - * @return String
524 - * @private
 596+ * Create paging links, as a helper method to getSectionPagingLinks().
 597+ *
 598+ * @param $until String The 'until' parameter for the generated URL
 599+ * @param $from String The 'from' parameter for the genererated URL
 600+ * @param $type String A prefix for parameters, 'page' or 'subcat' or
 601+ * 'file'
 602+ * @return String HTML
525603 */
526 - function pagingLinks( $title, $first, $last, $limit, $query = array() ) {
 604+ private function pagingLinks( $first, $last, $type = '' ) {
527605 global $wgLang;
528606 $sk = $this->getSkin();
529 - $limitText = $wgLang->formatNum( $limit );
 607+ $limitText = $wgLang->formatNum( $this->limit );
530608
531609 $prevLink = wfMsgExt( 'prevn', array( 'escape', 'parsemag' ), $limitText );
532610
533611 if ( $first != '' ) {
534 - $prevQuery = $query;
535 - $prevQuery['until'] = $first;
 612+ $prevQuery = $this->query;
 613+ $prevQuery["{$type}until"] = $first;
 614+ unset( $prevQuery["{$type}from"] );
536615 $prevLink = $sk->linkKnown(
537 - $title,
 616+ $this->title,
538617 $prevLink,
539618 array(),
540619 $prevQuery
@@ -543,10 +622,11 @@
544623 $nextLink = wfMsgExt( 'nextn', array( 'escape', 'parsemag' ), $limitText );
545624
546625 if ( $last != '' ) {
547 - $lastQuery = $query;
548 - $lastQuery['from'] = $last;
 626+ $lastQuery = $this->query;
 627+ $lastQuery["{$type}from"] = $last;
 628+ unset( $lastQuery["{$type}until"] );
549629 $nextLink = $sk->linkKnown(
550 - $title,
 630+ $this->title,
551631 $nextLink,
552632 array(),
553633 $lastQuery

Status & tagging log