r81671 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r81670‎ | r81671 | r81672 >
Date:00:57, 8 February 2011
Author:tstarling
Status:reverted (Comments)
Tags:
Comment:
Back out the changes which depend on the categorylinks schema change, so that it can be deployed separately:
* Approximately reverted r71174 (CategoryTree changes).
* Reverted r72457, r72509 (Collection, DPL, FlaggedRevs).
* Reverted the whole of CategoryPage.php back to r62481.
* Reverted LinksUpdate::getCategoryInsertions() and LinksUpdate::getExistingCategories() to how they were in 1.16.
* Reverted the categorylinks update portion of Title::moveTo() to how it was in 1.16.
* Reverted ApiQueryCategoryMembers.php to r79790 (before r80324 etc.)
* Reverted r81554 (Parser::getDefaultSort() empty string sortkey etc.)
* Core is lightly tested. Extensions are not tested.
Modified paths:
  • /branches/wmf/1.17wmf1/extensions/CategoryTree/CategoryTreeFunctions.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/Collection/Collection.body.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/FlaggedRevs/specialpages/UnreviewedPages_body.php (modified) (history)
  • /branches/wmf/1.17wmf1/extensions/intersection/DynamicPageList.php (modified) (history)
  • /branches/wmf/1.17wmf1/includes/CategoryPage.php (modified) (history)
  • /branches/wmf/1.17wmf1/includes/LinksUpdate.php (modified) (history)
  • /branches/wmf/1.17wmf1/includes/Title.php (modified) (history)
  • /branches/wmf/1.17wmf1/includes/api/ApiQueryCategoryMembers.php (modified) (history)
  • /branches/wmf/1.17wmf1/includes/parser/Parser.php (modified) (history)

Diff [purge]

Index: branches/wmf/1.17wmf1/extensions/FlaggedRevs/specialpages/UnreviewedPages_body.php
@@ -272,14 +272,6 @@
273273 $fields[] = 'cl_sortkey';
274274 $conds['cl_to'] = $this->category;
275275 $conds[] = 'cl_from = page_id';
276 - # Note: single NS always specified
277 - if( $this->namespace == NS_FILE ) {
278 - $conds['cl_type'] = 'file';
279 - } elseif( $this->namespace == NS_CATEGORY ) {
280 - $conds['cl_type'] = 'subcat';
281 - } else {
282 - $conds['cl_type'] = 'page';
283 - }
284276 $this->mIndexField = 'cl_sortkey';
285277 $useIndex = array( 'categorylinks' => 'cl_sortkey' );
286278 $groupBy = 'cl_sortkey,cl_from';
Index: branches/wmf/1.17wmf1/extensions/Collection/Collection.body.php
@@ -631,10 +631,10 @@
632632 }
633633 $db = wfGetDB( DB_SLAVE );
634634 $tables = array( 'page', 'categorylinks' );
635 - $fields = array( 'page_namespace', 'page_title' );
 635+ $fields = array( 'cl_from', 'cl_sortkey', 'page_namespace', 'page_title' );
636636 $options = array(
637637 'USE INDEX' => 'cl_sortkey',
638 - 'ORDER BY' => 'cl_type, cl_sortkey',
 638+ 'ORDER BY' => 'cl_sortkey',
639639 'LIMIT' => $limit + 1,
640640 );
641641 $where = array(
Index: branches/wmf/1.17wmf1/extensions/intersection/DynamicPageList.php
@@ -497,7 +497,7 @@
498498 $sSqlSort = 'page_id'; # Since they're never reused and increasing
499499 break;
500500 case 'categorysortkey':
501 - $sSqlSort = "c1.cl_type $sSqlOrder, c1.cl_sortkey";
 501+ $sSqlSort = 'c1.cl_sortkey';
502502 break;
503503 case 'popularity':
504504 $sSqlSort = 'page_counter';
Index: branches/wmf/1.17wmf1/extensions/CategoryTree/CategoryTreeFunctions.php
@@ -427,7 +427,7 @@
428428 'cl_from' );
429429 $where = array();
430430 $joins = array();
431 - $options = array( 'ORDER BY' => 'cl_type, cl_sortkey', 'LIMIT' => $wgCategoryTreeMaxChildren );
 431+ $options = array( 'ORDER BY' => 'cl_sortkey', 'LIMIT' => $wgCategoryTreeMaxChildren );
432432
433433 if ( $inverse ) {
434434 $joins['categorylinks'] = array( 'RIGHT JOIN', 'cl_to = page_title AND page_namespace = ' . NS_CATEGORY );
@@ -443,9 +443,9 @@
444444 $where['page_namespace'] = $namespaces;
445445 } elseif ( $mode != CT_MODE_ALL ) {
446446 if ( $mode == CT_MODE_PAGES ) {
447 - $where['cl_type'] = array( 'page', 'subcat' );
 447+ $where = array_merge( $where, array( 'page_namespace != ' . NS_IMAGE ) );
448448 } else {
449 - $where['cl_type'] = 'subcat';
 449+ $where['page_namespace'] = NS_CATEGORY;
450450 }
451451 }
452452 }
Index: branches/wmf/1.17wmf1/includes/CategoryPage.php
@@ -1,41 +1,33 @@
22 <?php
33 /**
4 - * Special handling for category description pages.
5 - * Modelled after ImagePage.php.
 4+ * Special handling for category description pages
 5+ * Modelled after ImagePage.php
66 *
7 - * @file
87 */
98
109 if ( !defined( 'MEDIAWIKI' ) )
1110 die( 1 );
1211
1312 /**
14 - * Special handling for category description pages, showing pages,
15 - * subcategories and file that belong to the category
1613 */
1714 class CategoryPage extends Article {
18 - # Subclasses can change this to override the viewer class.
19 - protected $mCategoryViewerClass = 'CategoryViewer';
20 -
2115 function view() {
2216 global $wgRequest, $wgUser;
2317
2418 $diff = $wgRequest->getVal( 'diff' );
2519 $diffOnly = $wgRequest->getBool( 'diffonly', $wgUser->getOption( 'diffonly' ) );
2620
27 - if ( isset( $diff ) && $diffOnly ) {
28 - return parent::view();
29 - }
 21+ if ( isset( $diff ) && $diffOnly )
 22+ return Article::view();
3023
31 - if ( !wfRunHooks( 'CategoryPageView', array( &$this ) ) ) {
 24+ if ( !wfRunHooks( 'CategoryPageView', array( &$this ) ) )
3225 return;
33 - }
3426
3527 if ( NS_CATEGORY == $this->mTitle->getNamespace() ) {
3628 $this->openShowCategory();
3729 }
3830
39 - parent::view();
 31+ Article::view();
4032
4133 if ( NS_CATEGORY == $this->mTitle->getNamespace() ) {
4234 $this->closeShowCategory();
@@ -60,14 +52,10 @@
6153
6254 function closeShowCategory() {
6355 global $wgOut, $wgRequest;
 56+ $from = $wgRequest->getVal( 'from' );
 57+ $until = $wgRequest->getVal( 'until' );
6458
65 - $from = $until = array();
66 - foreach ( array( 'page', 'subcat', 'file' ) as $type ) {
67 - $from[$type] = $wgRequest->getVal( "{$type}from" );
68 - $until[$type] = $wgRequest->getVal( "{$type}until" );
69 - }
70 -
71 - $viewer = new $this->mCategoryViewerClass( $this->mTitle, $from, $until, $wgRequest->getValues() );
 59+ $viewer = new CategoryViewer( $this->mTitle, $from, $until );
7260 $wgOut->addHTML( $viewer->getHTML() );
7361 }
7462 }
@@ -77,32 +65,27 @@
7866 $articles, $articles_start_char,
7967 $children, $children_start_char,
8068 $showGallery, $gallery,
81 - $imgsNoGalley, $imgsNoGallery_start_char,
82 - $skin, $collation;
83 - # Category object for this page
 69+ $skin;
 70+ /** Category object for this page */
8471 private $cat;
85 - # The original query array, to be used in generating paging links.
86 - private $query;
8772
88 - function __construct( $title, $from = '', $until = '', $query = array() ) {
 73+ function __construct( $title, $from = '', $until = '' ) {
8974 global $wgCategoryPagingLimit;
9075 $this->title = $title;
9176 $this->from = $from;
9277 $this->until = $until;
9378 $this->limit = $wgCategoryPagingLimit;
9479 $this->cat = Category::newFromTitle( $title );
95 - $this->query = $query;
96 - $this->collation = Collation::singleton();
97 - unset( $this->query['title'] );
9880 }
9981
10082 /**
10183 * Format the category data list.
10284 *
10385 * @return string HTML output
 86+ * @private
10487 */
105 - public function getHTML() {
106 - global $wgOut, $wgCategoryMagicGallery, $wgContLang;
 88+ function getHTML() {
 89+ global $wgOut, $wgCategoryMagicGallery, $wgCategoryPagingLimit, $wgContLang;
10790 wfProfileIn( __METHOD__ );
10891
10992 $this->showGallery = $wgCategoryMagicGallery && !$wgOut->mNoGallery;
@@ -145,9 +128,6 @@
146129 if ( $this->showGallery ) {
147130 $this->gallery = new ImageGallery();
148131 $this->gallery->setHideBadImages();
149 - } else {
150 - $this->imgsNoGallery = array();
151 - $this->imgsNoGallery_start_char = array();
152132 }
153133 }
154134
@@ -162,29 +142,26 @@
163143 /**
164144 * Add a subcategory to the internal lists, using a Category object
165145 */
166 - function addSubcategoryObject( Category $cat, $sortkey, $pageLength ) {
167 - // Subcategory; strip the 'Category' namespace from the link text.
 146+ function addSubcategoryObject( $cat, $sortkey, $pageLength ) {
168147 $title = $cat->getTitle();
169 -
170 - $link = $this->getSkin()->link( $title, $title->getText() );
171 - if ( $title->isRedirect() ) {
172 - // This didn't used to add redirect-in-category, but might
173 - // as well be consistent with the rest of the sections
174 - // on a category page.
175 - $link = '<span class="redirect-in-category">' . $link . '</span>';
176 - }
177 - $this->children[] = $link;
178 -
179 - $this->children_start_char[] =
180 - $this->getSubcategorySortChar( $cat->getTitle(), $sortkey );
 148+ $this->addSubcategory( $title, $sortkey, $pageLength );
181149 }
182150
183151 /**
184152 * Add a subcategory to the internal lists, using a title object
185153 * @deprecated kept for compatibility, please use addSubcategoryObject instead
186154 */
187 - function addSubcategory( Title $title, $sortkey, $pageLength ) {
188 - $this->addSubcategoryObject( Category::newFromTitle( $title ), $sortkey, $pageLength );
 155+ function addSubcategory( $title, $sortkey, $pageLength ) {
 156+ // Subcategory; strip the 'Category' namespace from the link text.
 157+ $this->children[] = $this->getSkin()->link(
 158+ $title,
 159+ null,
 160+ array(),
 161+ array(),
 162+ array( 'known', 'noclasses' )
 163+ );
 164+
 165+ $this->children_start_char[] = $this->getSubcategorySortChar( $title, $sortkey );
189166 }
190167
191168 /**
@@ -198,13 +175,11 @@
199176 global $wgContLang;
200177
201178 if ( $title->getPrefixedText() == $sortkey ) {
202 - $word = $title->getDBkey();
 179+ $firstChar = $wgContLang->firstChar( $title->getDBkey() );
203180 } else {
204 - $word = $sortkey;
 181+ $firstChar = $wgContLang->firstChar( $sortkey );
205182 }
206183
207 - $firstChar = $this->collation->getFirstLetter( $word );
208 -
209184 return $wgContLang->convert( $firstChar );
210185 }
211186
@@ -212,25 +187,14 @@
213188 * Add a page in the image namespace
214189 */
215190 function addImage( Title $title, $sortkey, $pageLength, $isRedirect = false ) {
216 - global $wgContLang;
217191 if ( $this->showGallery ) {
218 - $flip = $this->flip['file'];
219 - if ( $flip ) {
 192+ if ( $this->flip ) {
220193 $this->gallery->insert( $title );
221194 } else {
222195 $this->gallery->add( $title );
223196 }
224197 } else {
225 - $link = $this->getSkin()->link( $title );
226 - if ( $isRedirect ) {
227 - // This seems kind of pointless given 'mw-redirect' class,
228 - // but keeping for back-compatibility with user css.
229 - $link = '<span class="redirect-in-category">' . $link . '</span>';
230 - }
231 - $this->imgsNoGallery[] = $link;
232 -
233 - $this->imgsNoGallery_start_char[] = $wgContLang->convert(
234 - $this->collation->getFirstLetter( $sortkey ) );
 198+ $this->addPage( $title, $sortkey, $pageLength, $isRedirect );
235199 }
236200 }
237201
@@ -239,96 +203,74 @@
240204 */
241205 function addPage( $title, $sortkey, $pageLength, $isRedirect = false ) {
242206 global $wgContLang;
243 -
244 - $link = $this->getSkin()->link( $title );
245 - if ( $isRedirect ) {
246 - // This seems kind of pointless given 'mw-redirect' class,
247 - // but keeping for back-compatiability with user css.
248 - $link = '<span class="redirect-in-category">' . $link . '</span>';
249 - }
250 - $this->articles[] = $link;
251 -
252 - $this->articles_start_char[] = $wgContLang->convert(
253 - $this->collation->getFirstLetter( $sortkey ) );
 207+ $this->articles[] = $isRedirect
 208+ ? '<span class="redirect-in-category">' .
 209+ $this->getSkin()->link(
 210+ $title,
 211+ null,
 212+ array(),
 213+ array(),
 214+ array( 'known', 'noclasses' )
 215+ ) . '</span>'
 216+ : $this->getSkin()->makeSizeLinkObj( $pageLength, $title );
 217+ $this->articles_start_char[] = $wgContLang->convert( $wgContLang->firstChar( $sortkey ) );
254218 }
255219
256220 function finaliseCategoryState() {
257 - if ( $this->flip['subcat'] ) {
 221+ if ( $this->flip ) {
258222 $this->children = array_reverse( $this->children );
259223 $this->children_start_char = array_reverse( $this->children_start_char );
260 - }
261 - if ( $this->flip['page'] ) {
262224 $this->articles = array_reverse( $this->articles );
263225 $this->articles_start_char = array_reverse( $this->articles_start_char );
264226 }
265 - if ( !$this->showGallery && $this->flip['file'] ) {
266 - $this->imgsNoGallery = array_reverse( $this->imgsNoGallery );
267 - $this->imgsNoGallery_start_char = array_reverse( $this->imgsNoGallery_start_char );
268 - }
269227 }
270228
271229 function doCategoryQuery() {
272230 $dbr = wfGetDB( DB_SLAVE, 'category' );
 231+ if ( $this->from != '' ) {
 232+ $pageCondition = 'cl_sortkey >= ' . $dbr->addQuotes( $this->from );
 233+ $this->flip = false;
 234+ } elseif ( $this->until != '' ) {
 235+ $pageCondition = 'cl_sortkey < ' . $dbr->addQuotes( $this->until );
 236+ $this->flip = true;
 237+ } else {
 238+ $pageCondition = '1 = 1';
 239+ $this->flip = false;
 240+ }
273241
274 - $this->nextPage = array(
275 - 'page' => null,
276 - 'subcat' => null,
277 - 'file' => null,
 242+ $res = $dbr->select(
 243+ array( 'page', 'categorylinks', 'category' ),
 244+ array( 'page_title', 'page_namespace', 'page_len', 'page_is_redirect', 'cl_sortkey',
 245+ 'cat_id', 'cat_title', 'cat_subcats', 'cat_pages', 'cat_files' ),
 246+ array( $pageCondition, 'cl_to' => $this->title->getDBkey() ),
 247+ __METHOD__,
 248+ array( 'ORDER BY' => $this->flip ? 'cl_sortkey DESC' : 'cl_sortkey',
 249+ 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ),
 250+ 'LIMIT' => $this->limit + 1 ),
 251+ array( 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
 252+ 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY ) )
278253 );
279 - $this->flip = array( 'page' => false, 'subcat' => false, 'file' => false );
280254
281 - foreach ( array( 'page', 'subcat', 'file' ) as $type ) {
282 - # Get the sortkeys for start/end, if applicable. Note that if
283 - # the collation in the database differs from the one
284 - # set in $wgCategoryCollation, pagination might go totally haywire.
285 - $extraConds = array( 'cl_type' => $type );
286 - if ( $this->from[$type] !== null ) {
287 - $extraConds[] = 'cl_sortkey >= '
288 - . $dbr->addQuotes( $this->collation->getSortKey( $this->from[$type] ) );
289 - } elseif ( $this->until[$type] !== null ) {
290 - $extraConds[] = 'cl_sortkey < '
291 - . $dbr->addQuotes( $this->collation->getSortKey( $this->until[$type] ) );
292 - $this->flip[$type] = true;
 255+ $count = 0;
 256+ $this->nextPage = null;
 257+
 258+ while ( $x = $dbr->fetchObject ( $res ) ) {
 259+ if ( ++$count > $this->limit ) {
 260+ // We've reached the one extra which shows that there are
 261+ // additional pages to be had. Stop here...
 262+ $this->nextPage = $x->cl_sortkey;
 263+ break;
293264 }
294265
295 - $res = $dbr->select(
296 - array( 'page', 'categorylinks', 'category' ),
297 - array( 'page_id', 'page_title', 'page_namespace', 'page_len',
298 - 'page_is_redirect', 'cl_sortkey', 'cat_id', 'cat_title',
299 - 'cat_subcats', 'cat_pages', 'cat_files', 'cl_sortkey_prefix' ),
300 - array( 'cl_to' => $this->title->getDBkey() ) + $extraConds,
301 - __METHOD__,
302 - array(
303 - 'USE INDEX' => array( 'categorylinks' => 'cl_sortkey' ),
304 - 'LIMIT' => $this->limit + 1,
305 - 'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey',
306 - ),
307 - array(
308 - 'categorylinks' => array( 'INNER JOIN', 'cl_from = page_id' ),
309 - 'category' => array( 'LEFT JOIN', 'cat_title = page_title AND page_namespace = ' . NS_CATEGORY )
310 - )
311 - );
 266+ $title = Title::makeTitle( $x->page_namespace, $x->page_title );
312267
313 - $count = 0;
314 - foreach ( $res as $row ) {
315 - $title = Title::newFromRow( $row );
316 - $rawSortkey = $title->getCategorySortkey( $row->cl_sortkey_prefix );
317 -
318 - if ( ++$count > $this->limit ) {
319 - # We've reached the one extra which shows that there
320 - # are additional pages to be had. Stop here...
321 - $this->nextPage[$type] = $rawSortkey;
322 - break;
323 - }
324 -
325 - if ( $title->getNamespace() == NS_CATEGORY ) {
326 - $cat = Category::newFromRow( $row, $title );
327 - $this->addSubcategoryObject( $cat, $rawSortkey, $row->page_len );
328 - } elseif ( $title->getNamespace() == NS_FILE ) {
329 - $this->addImage( $title, $rawSortkey, $row->page_len, $row->page_is_redirect );
330 - } else {
331 - $this->addPage( $title, $rawSortkey, $row->page_len, $row->page_is_redirect );
332 - }
 268+ if ( $title->getNamespace() == NS_CATEGORY ) {
 269+ $cat = Category::newFromRow( $x, $title );
 270+ $this->addSubcategoryObject( $cat, $x->cl_sortkey, $x->page_len );
 271+ } elseif ( $this->showGallery && $title->getNamespace() == NS_FILE ) {
 272+ $this->addImage( $title, $x->cl_sortkey, $x->page_len, $x->page_is_redirect );
 273+ } else {
 274+ $this->addPage( $title, $x->cl_sortkey, $x->page_len, $x->page_is_redirect );
333275 }
334276 }
335277 }
@@ -352,9 +294,7 @@
353295 $r .= "<div id=\"mw-subcategories\">\n";
354296 $r .= '<h2>' . wfMsg( 'subcategories' ) . "</h2>\n";
355297 $r .= $countmsg;
356 - $r .= $this->getSectionPagingLinks( 'subcat' );
357298 $r .= $this->formatList( $this->children, $this->children_start_char );
358 - $r .= $this->getSectionPagingLinks( 'subcat' );
359299 $r .= "\n</div>";
360300 }
361301 return $r;
@@ -378,57 +318,36 @@
379319 $r = "<div id=\"mw-pages\">\n";
380320 $r .= '<h2>' . wfMsg( 'category_header', $ti ) . "</h2>\n";
381321 $r .= $countmsg;
382 - $r .= $this->getSectionPagingLinks( 'page' );
383322 $r .= $this->formatList( $this->articles, $this->articles_start_char );
384 - $r .= $this->getSectionPagingLinks( 'page' );
385323 $r .= "\n</div>";
386324 }
387325 return $r;
388326 }
389327
390328 function getImageSection() {
391 - $r = '';
392 - $rescnt = $this->showGallery ? $this->gallery->count() : count( $this->imgsNoGallery );
393 - if ( $rescnt > 0 ) {
 329+ if ( $this->showGallery && ! $this->gallery->isEmpty() ) {
394330 $dbcnt = $this->cat->getFileCount();
 331+ $rescnt = $this->gallery->count();
395332 $countmsg = $this->getCountMessage( $rescnt, $dbcnt, 'file' );
396333
397 - $r .= "<div id=\"mw-category-media\">\n";
398 - $r .= '<h2>' . wfMsg( 'category-media-header', htmlspecialchars( $this->title->getText() ) ) . "</h2>\n";
399 - $r .= $countmsg;
400 - $r .= $this->getSectionPagingLinks( 'file' );
401 - if ( $this->showGallery ) {
402 - $r .= $this->gallery->toHTML();
403 - } else {
404 - $r .= $this->formatList( $this->imgsNoGallery, $this->imgsNoGallery_start_char );
405 - }
406 - $r .= $this->getSectionPagingLinks( 'file' );
407 - $r .= "\n</div>";
 334+ return "<div id=\"mw-category-media\">\n" .
 335+ '<h2>' . wfMsg( 'category-media-header', htmlspecialchars( $this->title->getText() ) ) . "</h2>\n" .
 336+ $countmsg . $this->gallery->toHTML() . "\n</div>";
 337+ } else {
 338+ return '';
408339 }
409 - return $r;
410340 }
411341
412 - /**
413 - * Get the paging links for a section (subcats/pages/files), to go at the top and bottom
414 - * of the output.
415 - *
416 - * @param $type String: 'page', 'subcat', or 'file'
417 - * @return String: HTML output, possibly empty if there are no other pages
418 - */
419 - private function getSectionPagingLinks( $type ) {
420 - if ( $this->until[$type] !== null ) {
421 - return $this->pagingLinks( $this->nextPage[$type], $this->until[$type], $type );
422 - } elseif ( $this->nextPage[$type] !== null || $this->from[$type] !== null ) {
423 - return $this->pagingLinks( $this->from[$type], $this->nextPage[$type], $type );
 342+ function getCategoryBottom() {
 343+ if ( $this->until != '' ) {
 344+ return $this->pagingLinks( $this->title, $this->nextPage, $this->until, $this->limit );
 345+ } elseif ( $this->nextPage != '' || $this->from != '' ) {
 346+ return $this->pagingLinks( $this->title, $this->from, $this->nextPage, $this->limit );
424347 } else {
425348 return '';
426349 }
427350 }
428351
429 - function getCategoryBottom() {
430 - return '';
431 - }
432 -
433352 /**
434353 * Format a list of articles chunked by letter, either as a
435354 * bullet list or a columnar format, depending on the length.
@@ -441,10 +360,10 @@
442361 */
443362 function formatList( $articles, $articles_start_char, $cutoff = 6 ) {
444363 if ( count ( $articles ) > $cutoff ) {
445 - return self::columnList( $articles, $articles_start_char );
 364+ return $this->columnList( $articles, $articles_start_char );
446365 } elseif ( count( $articles ) > 0 ) {
447366 // for short lists of articles in categories.
448 - return self::shortList( $articles, $articles_start_char );
 367+ return $this->shortList( $articles, $articles_start_char );
449368 }
450369 return '';
451370 }
@@ -464,7 +383,7 @@
465384 * @return String
466385 * @private
467386 */
468 - static function columnList( $articles, $articles_start_char ) {
 387+ function columnList( $articles, $articles_start_char ) {
469388 $columns = array_combine( $articles, $articles_start_char );
470389 # Split into three columns
471390 $columns = array_chunk( $columns, ceil( count( $columns ) / 3 ), true /* preserve keys */ );
@@ -516,7 +435,7 @@
517436 * @return String
518437 * @private
519438 */
520 - static function shortList( $articles, $articles_start_char ) {
 439+ function shortList( $articles, $articles_start_char ) {
521440 $r = '<h3>' . htmlspecialchars( $articles_start_char[0] ) . "</h3>\n";
522441 $r .= '<ul><li>' . $articles[0] . '</li>';
523442 for ( $index = 1; $index < count( $articles ); $index++ )
@@ -533,27 +452,26 @@
534453 }
535454
536455 /**
537 - * Create paging links, as a helper method to getSectionPagingLinks().
538 - *
539 - * @param $first String The 'until' parameter for the generated URL
540 - * @param $last String The 'from' parameter for the genererated URL
541 - * @param $type String A prefix for parameters, 'page' or 'subcat' or
542 - * 'file'
543 - * @return String HTML
 456+ * @param $title Title object
 457+ * @param $first String
 458+ * @param $last String
 459+ * @param $limit Int
 460+ * @param $query Array: additional query options to pass
 461+ * @return String
 462+ * @private
544463 */
545 - private function pagingLinks( $first, $last, $type = '' ) {
 464+ function pagingLinks( $title, $first, $last, $limit, $query = array() ) {
546465 global $wgLang;
547466 $sk = $this->getSkin();
548 - $limitText = $wgLang->formatNum( $this->limit );
 467+ $limitText = $wgLang->formatNum( $limit );
549468
550469 $prevLink = wfMsgExt( 'prevn', array( 'escape', 'parsemag' ), $limitText );
551470
552471 if ( $first != '' ) {
553 - $prevQuery = $this->query;
554 - $prevQuery["{$type}until"] = $first;
555 - unset( $prevQuery["{$type}from"] );
 472+ $prevQuery = $query;
 473+ $prevQuery['until'] = $first;
556474 $prevLink = $sk->linkKnown(
557 - $this->title,
 475+ $title,
558476 $prevLink,
559477 array(),
560478 $prevQuery
@@ -563,11 +481,10 @@
564482 $nextLink = wfMsgExt( 'nextn', array( 'escape', 'parsemag' ), $limitText );
565483
566484 if ( $last != '' ) {
567 - $lastQuery = $this->query;
568 - $lastQuery["{$type}from"] = $last;
569 - unset( $lastQuery["{$type}until"] );
 485+ $lastQuery = $query;
 486+ $lastQuery['from'] = $last;
570487 $nextLink = $sk->linkKnown(
571 - $this->title,
 488+ $title,
572489 $nextLink,
573490 array(),
574491 $lastQuery
@@ -579,8 +496,8 @@
580497
581498 /**
582499 * What to do if the category table conflicts with the number of results
583 - * returned? This function says what. Each type is considered independantly
584 - * of the other types.
 500+ * returned? This function says what. It works the same whether the
 501+ * things being counted are articles, subcategories, or files.
585502 *
586503 * Note for grepping: uses the messages category-article-count,
587504 * category-article-count-limited, category-subcat-count,
@@ -603,28 +520,15 @@
604521 # than $this->limit and there's no offset. In this case we still
605522 # know the right figure.
606523 # 3) We have no idea.
 524+ $totalrescnt = count( $this->articles ) + count( $this->children ) +
 525+ ( $this->showGallery ? $this->gallery->count() : 0 );
607526
608 - # Check if there's a "from" or "until" for anything
609 -
610 - // This is a little ugly, but we seem to use different names
611 - // for the paging types then for the messages.
612 - if ( $type === 'article' ) {
613 - $pagingType = 'page';
614 - } else {
615 - $pagingType = $type;
616 - }
617 -
618 - $fromOrUntil = false;
619 - if ( $this->from[$pagingType] !== null || $this->until[$pagingType] !== null ) {
620 - $fromOrUntil = true;
621 - }
622 -
623 - if ( $dbcnt == $rescnt || ( ( $rescnt == $this->limit || $fromOrUntil )
624 - && $dbcnt > $rescnt ) )
 527+ if ( $dbcnt == $rescnt || ( ( $totalrescnt == $this->limit || $this->from
 528+ || $this->until ) && $dbcnt > $rescnt ) )
625529 {
626530 # Case 1: seems sane.
627531 $totalcnt = $dbcnt;
628 - } elseif ( $rescnt < $this->limit && !$fromOrUntil ) {
 532+ } elseif ( $totalrescnt < $this->limit && !$this->from && !$this->until ) {
629533 # Case 2: not sane, but salvageable. Use the number of results.
630534 # Since there are fewer than 200, we can also take this opportunity
631535 # to refresh the incorrect category table entry -- which should be
Index: branches/wmf/1.17wmf1/includes/parser/Parser.php
@@ -4996,19 +4996,15 @@
49974997
49984998 /**
49994999 * Accessor for $mDefaultSort
5000 - * Will use the empty string if none is set.
 5000+ * Will use the title/prefixed title if none is set
50015001 *
5002 - * This value is treated as a prefix, so the
5003 - * empty string is equivalent to sorting by
5004 - * page name.
5005 - *
50065002 * @return string
50075003 */
50085004 public function getDefaultSort() {
50095005 if ( $this->mDefaultSort !== false ) {
50105006 return $this->mDefaultSort;
50115007 } else {
5012 - return '';
 5008+ return $this->mTitle->getCategorySortkey();
50135009 }
50145010 }
50155011
Property changes on: branches/wmf/1.17wmf1/includes/parser/Parser.php
___________________________________________________________________
Modified: svn:mergeinfo
50165012 Reverse-merged /trunk/phase3/includes/parser/Parser.php:r81554
Index: branches/wmf/1.17wmf1/includes/api/ApiQueryCategoryMembers.php
@@ -65,28 +65,28 @@
6666 $fld_ids = isset( $prop['ids'] );
6767 $fld_title = isset( $prop['title'] );
6868 $fld_sortkey = isset( $prop['sortkey'] );
69 - $fld_sortkeyprefix = isset( $prop['sortkeyprefix'] );
7069 $fld_timestamp = isset( $prop['timestamp'] );
71 - $fld_type = isset( $prop['type'] );
7270
7371 if ( is_null( $resultPageSet ) ) {
74 - $this->addFields( array( 'cl_from', 'page_namespace', 'page_title' ) );
 72+ $this->addFields( array( 'cl_from', 'cl_sortkey', 'page_namespace', 'page_title' ) );
7573 $this->addFieldsIf( 'page_id', $fld_ids );
76 - $this->addFieldsIf( 'cl_sortkey_prefix', $fld_sortkeyprefix );
77 - $this->addFieldsIf( 'cl_sortkey', $fld_sortkey );
7874 } else {
7975 $this->addFields( $resultPageSet->getPageTableFields() ); // will include page_ id, ns, title
8076 $this->addFields( array( 'cl_from', 'cl_sortkey' ) );
8177 }
8278
8379 $this->addFieldsIf( 'cl_timestamp', $fld_timestamp || $params['sort'] == 'timestamp' );
84 - $this->addFieldsIf( 'cl_type', $fld_type );
85 -
8680 $this->addTables( array( 'page', 'categorylinks' ) ); // must be in this order for 'USE INDEX'
 81+ // Not needed after bug 10280 is applied to servers
 82+ if ( $params['sort'] == 'timestamp' ) {
 83+ $this->addOption( 'USE INDEX', 'cl_timestamp' );
 84+ } else {
 85+ $this->addOption( 'USE INDEX', 'cl_sortkey' );
 86+ }
8787
 88+ $this->addWhere( 'cl_from=page_id' );
 89+ $this->setContinuation( $params['continue'], $params['dir'] );
8890 $this->addWhereFld( 'cl_to', $categoryTitle->getDBkey() );
89 - $this->addWhereFld( 'cl_type', $params['type'] );
90 -
9191 // Scanning large datasets for rare categories sucks, and I already told
9292 // how to have efficient subcategory access :-) ~~~~ (oh well, domas)
9393 global $wgMiserMode;
@@ -96,35 +96,18 @@
9797 } else {
9898 $this->addWhereFld( 'page_namespace', $params['namespace'] );
9999 }
100 -
101 - $dir = $params['dir'] == 'asc' ? 'newer' : 'older';
102 -
103100 if ( $params['sort'] == 'timestamp' ) {
104 - $this->addWhereRange( 'cl_timestamp',
105 - $dir,
106 - $params['start'],
107 - $params['end'] );
108 -
109 - $this->addOption( 'USE INDEX', 'cl_timestamp' );
 101+ $this->addWhereRange( 'cl_timestamp', ( $params['dir'] == 'asc' ? 'newer' : 'older' ), $params['start'], $params['end'] );
110102 } else {
111 - // The below produces ORDER BY cl_type, cl_sortkey, cl_from, possibly with DESC added to each of them
112 - $this->addWhereRange( 'cl_type', $dir, null, null );
113 - $this->addWhereRange( 'cl_sortkey',
114 - $dir,
115 - $params['startsortkey'],
116 - $params['endsortkey'] );
117 - $this->addWhereRange( 'cl_from', $dir, null, null );
118 - $this->addOption( 'USE INDEX', 'cl_sortkey' );
 103+ $this->addWhereRange( 'cl_sortkey', ( $params['dir'] == 'asc' ? 'newer' : 'older' ), $params['startsortkey'], $params['endsortkey'] );
 104+ $this->addWhereRange( 'cl_from', ( $params['dir'] == 'asc' ? 'newer' : 'older' ), null, null );
119105 }
120106
121 - $this->setContinuation( $params['continue'], $params['dir'] );
122 -
123 - $this->addWhere( 'cl_from=page_id' );
124 -
125107 $limit = $params['limit'];
126108 $this->addOption( 'LIMIT', $limit + 1 );
127109
128110 $count = 0;
 111+ $lastSortKey = null;
129112 $res = $this->select( __METHOD__ );
130113 foreach ( $res as $row ) {
131114 if ( ++ $count > $limit ) {
@@ -133,7 +116,7 @@
134117 if ( $params['sort'] == 'timestamp' ) {
135118 $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->cl_timestamp ) );
136119 } else {
137 - $this->setContinueEnumParameter( 'continue', $row->cl_from );
 120+ $this->setContinueEnumParameter( 'continue', $this->getContinueStr( $row, $lastSortKey ) );
138121 }
139122 break;
140123 }
@@ -158,12 +141,6 @@
159142 if ( $fld_sortkey ) {
160143 $vals['sortkey'] = $row->cl_sortkey;
161144 }
162 - if ( $fld_sortkeyprefix ) {
163 - $vals['sortkeyprefix'] = $row->cl_sortkey_prefix;
164 - }
165 - if ( $fld_type ) {
166 - $vals['type'] = $row->cl_type;
167 - }
168145 if ( $fld_timestamp ) {
169146 $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $row->cl_timestamp );
170147 }
@@ -173,13 +150,14 @@
174151 if ( $params['sort'] == 'timestamp' ) {
175152 $this->setContinueEnumParameter( 'start', wfTimestamp( TS_ISO_8601, $row->cl_timestamp ) );
176153 } else {
177 - $this->setContinueEnumParameter( 'continue', $row->cl_from );
 154+ $this->setContinueEnumParameter( 'continue', $this->getContinueStr( $row, $lastSortKey ) );
178155 }
179156 break;
180157 }
181158 } else {
182159 $resultPageSet->processDbRow( $row );
183160 }
 161+ $lastSortKey = $row->cl_sortkey; // detect duplicate sortkeys
184162 }
185163
186164 if ( is_null( $resultPageSet ) ) {
@@ -188,6 +166,14 @@
189167 }
190168 }
191169
 170+ private function getContinueStr( $row, $lastSortKey ) {
 171+ $ret = $row->cl_sortkey . '|';
 172+ if ( $row->cl_sortkey == $lastSortKey ) { // duplicate sort key, add cl_from
 173+ $ret .= $row->cl_from;
 174+ }
 175+ return $ret;
 176+ }
 177+
192178 /**
193179 * Add DB WHERE clause to continue previous query based on 'continue' parameter
194180 */
@@ -196,11 +182,26 @@
197183 return; // This is not a continuation request
198184 }
199185
200 - $encFrom = $this->getDB()->addQuotes( intval( $continue ) );
 186+ $pos = strrpos( $continue, '|' );
 187+ $sortkey = substr( $continue, 0, $pos );
 188+ $fromstr = substr( $continue, $pos + 1 );
 189+ $from = intval( $fromstr );
201190
202 - $op = ( $dir == 'desc' ? '<=' : '>=' );
 191+ if ( $from == 0 && strlen( $fromstr ) > 0 ) {
 192+ $this->dieUsage( 'Invalid continue param. You should pass the original value returned by the previous query', 'badcontinue' );
 193+ }
203194
204 - $this->addWhere( "cl_from $op $encFrom" );
 195+ $encSortKey = $this->getDB()->addQuotes( $sortkey );
 196+ $encFrom = $this->getDB()->addQuotes( $from );
 197+
 198+ $op = ( $dir == 'desc' ? '<' : '>' );
 199+
 200+ if ( $from != 0 ) {
 201+ // Duplicate sort key continue
 202+ $this->addWhere( "cl_sortkey$op$encSortKey OR (cl_sortkey=$encSortKey AND cl_from$op=$encFrom)" );
 203+ } else {
 204+ $this->addWhere( "cl_sortkey$op=$encSortKey" );
 205+ }
205206 }
206207
207208 public function getAllowedParams() {
@@ -216,8 +217,6 @@
217218 'ids',
218219 'title',
219220 'sortkey',
220 - 'sortkeyprefix',
221 - 'type',
222221 'timestamp',
223222 )
224223 ),
@@ -225,15 +224,6 @@
226225 ApiBase::PARAM_ISMULTI => true,
227226 ApiBase::PARAM_TYPE => 'namespace',
228227 ),
229 - 'type' => array(
230 - ApiBase::PARAM_ISMULTI => true,
231 - ApiBase::PARAM_DFLT => 'page|subcat|file',
232 - ApiBase::PARAM_TYPE => array(
233 - 'page',
234 - 'subcat',
235 - 'file'
236 - )
237 - ),
238228 'continue' => null,
239229 'limit' => array(
240230 ApiBase::PARAM_TYPE => 'limit',
@@ -274,15 +264,12 @@
275265 'title' => 'Which category to enumerate (required). Must include Category: prefix',
276266 'prop' => array(
277267 'What pieces of information to include',
278 - ' ids - Adds the page ID',
279 - ' title - Adds the title and namespace ID of the page',
280 - ' sortkey - Adds the sortkey used for sorting in the category (may not be human-readble)',
281 - ' sortkeyprefix - Adds the sortkey prefix used for sorting in the category (human-readable part of the sortkey)',
282 - ' type - Adds the type that the page has been categorised as (page, subcat or file)',
283 - ' timestamp - Adds the timestamp of when the page was included',
 268+ ' ids - Adds the page id',
 269+ ' title - Adds the title and namespace id of the page',
 270+ ' sortkey - Adds the sortkey used for the category',
 271+ ' timestamp - Adds the timestamp of when the page was included',
284272 ),
285273 'namespace' => 'Only include pages in these namespaces',
286 - 'type' => 'What type of category members to include',
287274 'sort' => 'Property to sort by',
288275 'dir' => 'In which direction to sort',
289276 'start' => "Timestamp to start listing from. Can only be used with {$p}sort=timestamp",
Index: branches/wmf/1.17wmf1/includes/LinksUpdate.php
@@ -72,11 +72,10 @@
7373 # it truncated by DB, and then doesn't get
7474 # matched when comparing existing vs current
7575 # categories, causing bug 25254.
76 - # Also. substr behaves weird when given "".
77 - if ( $sortkey !== '' ) {
78 - $sortkey = substr( $sortkey, 0, 255 );
79 - }
 76+ $sortkey = substr( $sortkey, 0, 255 );
8077 }
 78+ var_dump( $this->mCategories );
 79+
8180
8281 $this->mRecursive = $recursive;
8382
@@ -435,39 +434,20 @@
436435 * @private
437436 */
438437 function getCategoryInsertions( $existing = array() ) {
439 - global $wgContLang, $wgCategoryCollation;
 438+ global $wgContLang;
440439 $diffs = array_diff_assoc( $this->mCategories, $existing );
441440 $arr = array();
442 - foreach ( $diffs as $name => $prefix ) {
 441+ foreach ( $diffs as $name => $sortkey ) {
443442 $nt = Title::makeTitleSafe( NS_CATEGORY, $name );
444443 $wgContLang->findVariantLink( $name, $nt, true );
445 -
446 - if ( $this->mTitle->getNamespace() == NS_CATEGORY ) {
447 - $type = 'subcat';
448 - } elseif ( $this->mTitle->getNamespace() == NS_FILE ) {
449 - $type = 'file';
450 - } else {
451 - $type = 'page';
452 - }
453 -
454 - # Treat custom sortkeys as a prefix, so that if multiple
455 - # things are forced to sort as '*' or something, they'll
456 - # sort properly in the category rather than in page_id
457 - # order or such.
458 - $sortkey = Collation::singleton()->getSortKey(
459 - $this->mTitle->getCategorySortkey( $prefix ) );
460 -
461444 $arr[] = array(
462445 'cl_from' => $this->mId,
463446 'cl_to' => $name,
464447 'cl_sortkey' => $sortkey,
465 - 'cl_timestamp' => $this->mDb->timestamp(),
466 - 'cl_sortkey_prefix' => $prefix,
467 - 'cl_collation' => $wgCategoryCollation,
468 - 'cl_type' => $type,
 448+ 'cl_timestamp' => $this->mDb->timestamp()
469449 );
470450 }
471 - return $arr;
 451+ return $arr;
472452 }
473453
474454 /**
@@ -687,13 +667,14 @@
688668 * @private
689669 */
690670 function getExistingCategories() {
691 - $res = $this->mDb->select( 'categorylinks', array( 'cl_to', 'cl_sortkey_prefix' ),
 671+ $res = $this->mDb->select( 'categorylinks', array( 'cl_to', 'cl_sortkey' ),
692672 array( 'cl_from' => $this->mId ), __METHOD__, $this->mOptions );
693673 $arr = array();
694 - foreach ( $res as $row ) {
695 - $arr[$row->cl_to] = $row->cl_sortkey_prefix;
 674+ while ( $row = $this->mDb->fetchObject( $res ) ) {
 675+ $arr[$row->cl_to] = $row->cl_sortkey;
696676 }
697 - return $arr;
 677+ $this->mDb->freeResult( $res );
 678+ return $arr;
698679 }
699680
700681 /**
Index: branches/wmf/1.17wmf1/includes/Title.php
@@ -3102,22 +3102,27 @@
31033103 }
31043104 $redirid = $this->getArticleID();
31053105
3106 - // Refresh the sortkey for this row. Be careful to avoid resetting
3107 - // cl_timestamp, which may disturb time-based lists on some sites.
3108 - $prefix = $dbw->selectField(
3109 - 'categorylinks',
3110 - 'cl_sortkey_prefix',
3111 - array( 'cl_from' => $pageid ),
3112 - __METHOD__
3113 - );
 3106+ // Category memberships include a sort key which may be customized.
 3107+ // If it's left as the default (the page title), we need to update
 3108+ // the sort key to match the new title.
 3109+ //
 3110+ // Be careful to avoid resetting cl_timestamp, which may disturb
 3111+ // time-based lists on some sites.
 3112+ //
 3113+ // Warning -- if the sort key is *explicitly* set to the old title,
 3114+ // we can't actually distinguish it from a default here, and it'll
 3115+ // be set to the new title even though it really shouldn't.
 3116+ // It'll get corrected on the next edit, but resetting cl_timestamp.
31143117 $dbw->update( 'categorylinks',
31153118 array(
3116 - 'cl_sortkey' => Collation::singleton()->getSortKey(
3117 - $nt->getCategorySortkey( $prefix ) ),
 3119+ 'cl_sortkey' => $nt->getPrefixedText(),
31183120 'cl_timestamp=cl_timestamp' ),
3119 - array( 'cl_from' => $pageid ),
 3121+ array(
 3122+ 'cl_from' => $pageid,
 3123+ 'cl_sortkey' => $this->getPrefixedText() ),
31203124 __METHOD__ );
31213125
 3126+
31223127 if ( $protected ) {
31233128 # Protect the redirect title as the title used to be...
31243129 $dbw->insertSelect( 'page_restrictions', 'page_restrictions',

Follow-up revisions

RevisionCommit summaryAuthorDate
r81686rm var_dump from r81671tstarling03:23, 8 February 2011
r81831Follow up to r81829. Poison var_dump, so that debug statements like r81671 ca...platonides17:36, 9 February 2011
r835241.17wmf1: Revert r81671 (Back out category collation changes) and followup r8...catrope15:14, 8 March 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r62481Random indentation and code formatting updates. No functional changes.siebrand22:07, 14 February 2010
r71174Adapt CategoryTree to the new schema...simetrical21:57, 16 August 2010
r72457Update Collection and intersection for new schema...simetrical21:16, 5 September 2010
r72509(bug 25084) Update FlaggedRevs for new categorylinks schema. Add cl_type to t...demon20:23, 6 September 2010
r79790Remove one invalid errors, add 2 that could be returnedreedy02:29, 7 January 2011
r80324Start of bug 24650 Fix API to work with categorylinks changes...reedy21:08, 14 January 2011
r81554(follow up r79706 to address CR comments) Simplify some of the logic in Links...bawolff02:16, 5 February 2011

Comments

#Comment by Brion VIBBER (talk | contribs)   03:20, 8 February 2011

stray var_dump in LinksUpdate

Status & tagging log