MediaWiki  master
CategoryViewer.php
Go to the documentation of this file.
1 <?php
23 use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
25 
27  use ProtectedHookAccessorTrait;
28 
30  public $limit;
31 
33  public $from;
34 
36  public $until;
37 
39  public $articles;
40 
43 
45  public $children;
46 
49 
51  public $showGallery;
52 
55 
58 
60  public $nextPage;
61 
63  protected $prevPage;
64 
66  public $flip;
67 
69  public $title;
70 
72  public $collation;
73 
75  public $gallery;
76 
78  private $cat;
79 
81  private $query;
82 
92  public function __construct( $title, IContextSource $context, $from = [],
93  $until = [], $query = []
94  ) {
95  $this->title = $title;
96  $this->setContext( $context );
97  $this->getOutput()->addModuleStyles( [
98  'mediawiki.action.view.categoryPage.styles'
99  ] );
100  $this->from = $from;
101  $this->until = $until;
102  $this->limit = $context->getConfig()->get( 'CategoryPagingLimit' );
103  $this->cat = Category::newFromTitle( $title );
104  $this->query = $query;
105  $this->collation = Collation::singleton();
106  unset( $this->query['title'] );
107  }
108 
114  public function getHTML() {
115  $this->showGallery = $this->getConfig()->get( 'CategoryMagicGallery' )
116  && !$this->getOutput()->mNoGallery;
117 
118  $this->clearCategoryState();
119  $this->doCategoryQuery();
120  $this->finaliseCategoryState();
121 
122  $r = $this->getSubcategorySection() .
123  $this->getPagesSection() .
124  $this->getImageSection();
125 
126  if ( $r == '' ) {
127  // If there is no category content to display, only
128  // show the top part of the navigation links.
129  // @todo FIXME: Cannot be completely suppressed because it
130  // is unknown if 'until' or 'from' makes this
131  // give 0 results.
132  $r = $this->getCategoryTop();
133  } else {
134  $r = $this->getCategoryTop() .
135  $r .
136  $this->getCategoryBottom();
137  }
138 
139  // Give a proper message if category is empty
140  if ( $r == '' ) {
141  $r = $this->msg( 'category-empty' )->parseAsBlock();
142  }
143 
144  $lang = $this->getLanguage();
145  $attribs = [
146  'class' => 'mw-category-generated',
147  'lang' => $lang->getHtmlCode(),
148  'dir' => $lang->getDir()
149  ];
150  # put a div around the headings which are in the user language
151  $r = Html::openElement( 'div', $attribs ) . $r . '</div>';
152 
153  return $r;
154  }
155 
156  protected function clearCategoryState() {
157  $this->articles = [];
158  $this->articles_start_char = [];
159  $this->children = [];
160  $this->children_start_char = [];
161  if ( $this->showGallery ) {
162  // Note that null for mode is taken to mean use default.
163  $mode = $this->getRequest()->getVal( 'gallerymode', null );
164  try {
165  $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
166  } catch ( Exception $e ) {
167  // User specified something invalid, fallback to default.
168  $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
169  }
170 
171  $this->gallery->setHideBadImages();
172  } else {
173  $this->imgsNoGallery = [];
174  $this->imgsNoGallery_start_char = [];
175  }
176  }
177 
184  public function addSubcategoryObject( Category $cat, $sortkey, $pageLength ) {
185  // Subcategory; strip the 'Category' namespace from the link text.
186  $title = $cat->getTitle();
187 
188  $this->children[] = $this->generateLink(
189  'subcat',
190  $title,
191  $title->isRedirect(),
192  htmlspecialchars( $title->getText() )
193  );
194 
195  $this->children_start_char[] =
196  $this->getSubcategorySortChar( $cat->getTitle(), $sortkey );
197  }
198 
199  private function generateLink( $type, Title $title, $isRedirect, $html = null ) {
200  $link = null;
201  $this->getHookRunner()->onCategoryViewer__generateLink( $type, $title, $html, $link );
202  if ( $link === null ) {
203  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
204  if ( $html !== null ) {
205  $html = new HtmlArmor( $html );
206  }
207  $link = $linkRenderer->makeLink( $title, $html );
208  }
209  if ( $isRedirect ) {
210  $link = '<span class="redirect-in-category">' . $link . '</span>';
211  }
212 
213  return $link;
214  }
215 
227  public function getSubcategorySortChar( $title, $sortkey ) {
228  if ( $title->getPrefixedText() == $sortkey ) {
229  $word = $title->getDBkey();
230  } else {
231  $word = $sortkey;
232  }
233 
234  $firstChar = $this->collation->getFirstLetter( $word );
235 
236  return MediaWikiServices::getInstance()->getContentLanguage()->convert( $firstChar );
237  }
238 
246  public function addImage( Title $title, $sortkey, $pageLength, $isRedirect = false ) {
247  if ( $this->showGallery ) {
248  $flip = $this->flip['file'];
249  if ( $flip ) {
250  $this->gallery->insert( $title );
251  } else {
252  $this->gallery->add( $title );
253  }
254  } else {
255  $this->imgsNoGallery[] = $this->generateLink( 'image', $title, $isRedirect );
256 
257  $this->imgsNoGallery_start_char[] = MediaWikiServices::getInstance()->
258  getContentLanguage()->convert( $this->collation->getFirstLetter( $sortkey ) );
259  }
260  }
261 
269  public function addPage( $title, $sortkey, $pageLength, $isRedirect = false ) {
270  $this->articles[] = $this->generateLink( 'page', $title, $isRedirect );
271 
272  $this->articles_start_char[] = MediaWikiServices::getInstance()->
273  getContentLanguage()->convert( $this->collation->getFirstLetter( $sortkey ) );
274  }
275 
276  protected function finaliseCategoryState() {
277  if ( $this->flip['subcat'] ) {
278  $this->children = array_reverse( $this->children );
279  $this->children_start_char = array_reverse( $this->children_start_char );
280  }
281  if ( $this->flip['page'] ) {
282  $this->articles = array_reverse( $this->articles );
283  $this->articles_start_char = array_reverse( $this->articles_start_char );
284  }
285  if ( !$this->showGallery && $this->flip['file'] ) {
286  $this->imgsNoGallery = array_reverse( $this->imgsNoGallery );
287  $this->imgsNoGallery_start_char = array_reverse( $this->imgsNoGallery_start_char );
288  }
289  }
290 
291  protected function doCategoryQuery() {
292  $dbr = wfGetDB( DB_REPLICA, 'category' );
293 
294  $this->nextPage = [
295  'page' => null,
296  'subcat' => null,
297  'file' => null,
298  ];
299  $this->prevPage = [
300  'page' => null,
301  'subcat' => null,
302  'file' => null,
303  ];
304 
305  $this->flip = [ 'page' => false, 'subcat' => false, 'file' => false ];
306 
307  foreach ( [ 'page', 'subcat', 'file' ] as $type ) {
308  # Get the sortkeys for start/end, if applicable. Note that if
309  # the collation in the database differs from the one
310  # set in $wgCategoryCollation, pagination might go totally haywire.
311  $extraConds = [ 'cl_type' => $type ];
312  if ( isset( $this->from[$type] ) ) {
313  $extraConds[] = 'cl_sortkey >= '
314  . $dbr->addQuotes( $this->collation->getSortKey( $this->from[$type] ) );
315  } elseif ( isset( $this->until[$type] ) ) {
316  $extraConds[] = 'cl_sortkey < '
317  . $dbr->addQuotes( $this->collation->getSortKey( $this->until[$type] ) );
318  $this->flip[$type] = true;
319  }
320 
321  $res = $dbr->select(
322  [ 'page', 'categorylinks', 'category' ],
323  array_merge(
325  [
326  'page_namespace',
327  'page_title',
328  'cl_sortkey',
329  'cat_id',
330  'cat_title',
331  'cat_subcats',
332  'cat_pages',
333  'cat_files',
334  'cl_sortkey_prefix',
335  'cl_collation'
336  ]
337  ),
338  array_merge( [ 'cl_to' => $this->title->getDBkey() ], $extraConds ),
339  __METHOD__,
340  [
341  'USE INDEX' => [ 'categorylinks' => 'cl_sortkey' ],
342  'LIMIT' => $this->limit + 1,
343  'ORDER BY' => $this->flip[$type] ? 'cl_sortkey DESC' : 'cl_sortkey',
344  ],
345  [
346  'categorylinks' => [ 'JOIN', 'cl_from = page_id' ],
347  'category' => [ 'LEFT JOIN', [
348  'cat_title = page_title',
349  'page_namespace' => NS_CATEGORY
350  ] ]
351  ]
352  );
353 
354  $this->getHookRunner()->onCategoryViewer__doCategoryQuery( $type, $res );
355  $linkCache = MediaWikiServices::getInstance()->getLinkCache();
356 
357  $count = 0;
358  foreach ( $res as $row ) {
359  $title = Title::newFromRow( $row );
360  $linkCache->addGoodLinkObjFromRow( $title, $row );
361 
362  if ( $row->cl_collation === '' ) {
363  // Hack to make sure that while updating from 1.16 schema
364  // and db is inconsistent, that the sky doesn't fall.
365  // See r83544. Could perhaps be removed in a couple decades...
366  $humanSortkey = $row->cl_sortkey;
367  } else {
368  $humanSortkey = $title->getCategorySortkey( $row->cl_sortkey_prefix );
369  }
370 
371  if ( ++$count > $this->limit ) {
372  # We've reached the one extra which shows that there
373  # are additional pages to be had. Stop here...
374  $this->nextPage[$type] = $humanSortkey;
375  break;
376  }
377  if ( $count == $this->limit ) {
378  $this->prevPage[$type] = $humanSortkey;
379  }
380 
381  if ( $title->getNamespace() == NS_CATEGORY ) {
382  $cat = Category::newFromRow( $row, $title );
383  $this->addSubcategoryObject( $cat, $humanSortkey, $row->page_len );
384  } elseif ( $title->getNamespace() == NS_FILE ) {
385  $this->addImage( $title, $humanSortkey, $row->page_len, $row->page_is_redirect );
386  } else {
387  $this->addPage( $title, $humanSortkey, $row->page_len, $row->page_is_redirect );
388  }
389  }
390  }
391  }
392 
396  protected function getCategoryTop() {
397  $r = $this->getCategoryBottom();
398  return $r === ''
399  ? $r
400  : "<br style=\"clear:both;\"/>\n" . $r;
401  }
402 
406  protected function getSubcategorySection() {
407  # Don't show subcategories section if there are none.
408  $r = '';
409  $rescnt = count( $this->children );
410  $dbcnt = $this->cat->getSubcatCount();
411  // This function should be called even if the result isn't used, it has side-effects
412  $countmsg = $this->getCountMessage( $rescnt, $dbcnt, 'subcat' );
413 
414  if ( $rescnt > 0 ) {
415  # Showing subcategories
416  $r .= "<div id=\"mw-subcategories\">\n";
417  $r .= '<h2>' . $this->msg( 'subcategories' )->parse() . "</h2>\n";
418  $r .= $countmsg;
419  $r .= $this->getSectionPagingLinks( 'subcat' );
420  $r .= $this->formatList( $this->children, $this->children_start_char );
421  $r .= $this->getSectionPagingLinks( 'subcat' );
422  $r .= "\n</div>";
423  }
424  return $r;
425  }
426 
430  protected function getPagesSection() {
431  $name = $this->getOutput()->getUnprefixedDisplayTitle();
432  # Don't show articles section if there are none.
433  $r = '';
434 
435  # @todo FIXME: Here and in the other two sections: we don't need to bother
436  # with this rigmarole if the entire category contents fit on one page
437  # and have already been retrieved. We can just use $rescnt in that
438  # case and save a query and some logic.
439  $dbcnt = $this->cat->getPageCount() - $this->cat->getSubcatCount()
440  - $this->cat->getFileCount();
441  $rescnt = count( $this->articles );
442  // This function should be called even if the result isn't used, it has side-effects
443  $countmsg = $this->getCountMessage( $rescnt, $dbcnt, 'article' );
444 
445  if ( $rescnt > 0 ) {
446  $r = "<div id=\"mw-pages\">\n";
447  $r .= '<h2>' . $this->msg( 'category_header' )->rawParams( $name )->parse() . "</h2>\n";
448  $r .= $countmsg;
449  $r .= $this->getSectionPagingLinks( 'page' );
450  $r .= $this->formatList( $this->articles, $this->articles_start_char );
451  $r .= $this->getSectionPagingLinks( 'page' );
452  $r .= "\n</div>";
453  }
454  return $r;
455  }
456 
460  protected function getImageSection() {
461  $name = $this->getOutput()->getUnprefixedDisplayTitle();
462  $r = '';
463  $rescnt = $this->showGallery ? $this->gallery->count() : count( $this->imgsNoGallery );
464  $dbcnt = $this->cat->getFileCount();
465  // This function should be called even if the result isn't used, it has side-effects
466  $countmsg = $this->getCountMessage( $rescnt, $dbcnt, 'file' );
467 
468  if ( $rescnt > 0 ) {
469  $r .= "<div id=\"mw-category-media\">\n";
470  $r .= '<h2>' .
471  $this->msg( 'category-media-header' )->rawParams( $name )->parse() .
472  "</h2>\n";
473  $r .= $countmsg;
474  $r .= $this->getSectionPagingLinks( 'file' );
475  if ( $this->showGallery ) {
476  $r .= $this->gallery->toHTML();
477  } else {
478  $r .= $this->formatList( $this->imgsNoGallery, $this->imgsNoGallery_start_char );
479  }
480  $r .= $this->getSectionPagingLinks( 'file' );
481  $r .= "\n</div>";
482  }
483  return $r;
484  }
485 
493  private function getSectionPagingLinks( $type ) {
494  if ( isset( $this->until[$type] ) ) {
495  // The new value for the until parameter should be pointing to the first
496  // result displayed on the page which is the second last result retrieved
497  // from the database.The next link should have a from parameter pointing
498  // to the until parameter of the current page.
499  if ( $this->nextPage[$type] !== null ) {
500  return $this->pagingLinks( $this->prevPage[$type], $this->until[$type], $type );
501  } else {
502  // If the nextPage variable is null, it means that we have reached the first page
503  // and therefore the previous link should be disabled.
504  return $this->pagingLinks( null, $this->until[$type], $type );
505  }
506  } elseif ( $this->nextPage[$type] !== null || isset( $this->from[$type] ) ) {
507  return $this->pagingLinks( $this->from[$type], $this->nextPage[$type], $type );
508  } else {
509  return '';
510  }
511  }
512 
516  protected function getCategoryBottom() {
517  return '';
518  }
519 
530  private function formatList( $articles, $articles_start_char, $cutoff = 6 ) {
531  $list = '';
532  if ( count( $articles ) > $cutoff ) {
534  } elseif ( count( $articles ) > 0 ) {
535  // for short lists of articles in categories.
537  }
538 
539  $pageLang = $this->title->getPageLanguage();
540  $attribs = [ 'lang' => $pageLang->getHtmlCode(), 'dir' => $pageLang->getDir(),
541  'class' => 'mw-content-' . $pageLang->getDir() ];
542  $list = Html::rawElement( 'div', $attribs, $list );
543 
544  return $list;
545  }
546 
561  public static function columnList( $articles, $articles_start_char ) {
562  $columns = array_combine( $articles, $articles_start_char );
563 
564  $ret = Html::openElement( 'div', [ 'class' => 'mw-category' ] );
565 
566  $colContents = [];
567 
568  # Kind of like array_flip() here, but we keep duplicates in an
569  # array instead of dropping them.
570  foreach ( $columns as $article => $char ) {
571  if ( !isset( $colContents[$char] ) ) {
572  $colContents[$char] = [];
573  }
574  $colContents[$char][] = $article;
575  }
576 
577  foreach ( $colContents as $char => $articles ) {
578  # Change space to non-breaking space to keep headers aligned
579  $h3char = $char === ' ' ? "\u{00A0}" : htmlspecialchars( $char );
580 
581  $ret .= '<div class="mw-category-group"><h3>' . $h3char;
582  $ret .= "</h3>\n";
583 
584  $ret .= '<ul><li>';
585  $ret .= implode( "</li>\n<li>", $articles );
586  $ret .= '</li></ul></div>';
587 
588  }
589 
590  $ret .= Html::closeElement( 'div' );
591  return $ret;
592  }
593 
602  public static function shortList( $articles, $articles_start_char ) {
603  $r = '<h3>' . htmlspecialchars( $articles_start_char[0] ) . "</h3>\n";
604  $r .= '<ul><li>' . $articles[0] . '</li>';
605  $articleCount = count( $articles );
606  for ( $index = 1; $index < $articleCount; $index++ ) {
607  if ( $articles_start_char[$index] != $articles_start_char[$index - 1] ) {
608  $r .= "</ul><h3>" . htmlspecialchars( $articles_start_char[$index] ) . "</h3>\n<ul>";
609  }
610 
611  $r .= "<li>{$articles[$index]}</li>";
612  }
613  $r .= '</ul>';
614  return $r;
615  }
616 
626  private function pagingLinks( $first, $last, $type = '' ) {
627  $prevLink = $this->msg( 'prev-page' )->escaped();
628 
629  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
630  if ( $first != '' ) {
631  $prevQuery = $this->query;
632  $prevQuery["{$type}until"] = $first;
633  unset( $prevQuery["{$type}from"] );
634  $prevLink = $linkRenderer->makeKnownLink(
635  $this->addFragmentToTitle( $this->title, $type ),
636  new HtmlArmor( $prevLink ),
637  [],
638  $prevQuery
639  );
640  }
641 
642  $nextLink = $this->msg( 'next-page' )->escaped();
643 
644  if ( $last != '' ) {
645  $lastQuery = $this->query;
646  $lastQuery["{$type}from"] = $last;
647  unset( $lastQuery["{$type}until"] );
648  $nextLink = $linkRenderer->makeKnownLink(
649  $this->addFragmentToTitle( $this->title, $type ),
650  new HtmlArmor( $nextLink ),
651  [],
652  $lastQuery
653  );
654  }
655 
656  return $this->msg( 'categoryviewer-pagedlinks' )->rawParams( $prevLink, $nextLink )->escaped();
657  }
658 
668  private function addFragmentToTitle( $title, $section ) {
669  switch ( $section ) {
670  case 'page':
671  $fragment = 'mw-pages';
672  break;
673  case 'subcat':
674  $fragment = 'mw-subcategories';
675  break;
676  case 'file':
677  $fragment = 'mw-category-media';
678  break;
679  default:
680  throw new MWException( __METHOD__ .
681  " Invalid section $section." );
682  }
683 
685  $title->getDBkey(), $fragment );
686  }
687 
698  private function getCountMessage( $rescnt, $dbcnt, $type ) {
699  // There are three cases:
700  // 1) The category table figure seems sane. It might be wrong, but
701  // we can't do anything about it if we don't recalculate it on ev-
702  // ery category view.
703  // 2) The category table figure isn't sane, like it's smaller than the
704  // number of actual results, *but* the number of results is less
705  // than $this->limit and there's no offset. In this case we still
706  // know the right figure.
707  // 3) We have no idea.
708 
709  // Check if there's a "from" or "until" for anything
710 
711  // This is a little ugly, but we seem to use different names
712  // for the paging types then for the messages.
713  if ( $type === 'article' ) {
714  $pagingType = 'page';
715  } else {
716  $pagingType = $type;
717  }
718 
719  $fromOrUntil = false;
720  if ( isset( $this->from[$pagingType] ) || isset( $this->until[$pagingType] ) ) {
721  $fromOrUntil = true;
722  }
723 
724  if ( $dbcnt == $rescnt ||
725  ( ( $rescnt == $this->limit || $fromOrUntil ) && $dbcnt > $rescnt )
726  ) {
727  // Case 1: seems sane.
728  $totalcnt = $dbcnt;
729  } elseif ( $rescnt < $this->limit && !$fromOrUntil ) {
730  // Case 2: not sane, but salvageable. Use the number of results.
731  $totalcnt = $rescnt;
732  } else {
733  // Case 3: hopeless. Don't give a total count at all.
734  // Messages: category-subcat-count-limited, category-article-count-limited,
735  // category-file-count-limited
736  return $this->msg( "category-$type-count-limited" )->numParams( $rescnt )->parseAsBlock();
737  }
738  // Messages: category-subcat-count, category-article-count, category-file-count
739  return $this->msg( "category-$type-count" )->numParams( $rescnt, $totalcnt )->parseAsBlock();
740  }
741 }
CategoryViewer\$children
array $children
Definition: CategoryViewer.php:45
CategoryViewer\$query
array $query
The original query array, to be used in generating paging links.
Definition: CategoryViewer.php:81
Category\getTitle
getTitle()
Definition: Category.php:258
ContextSource\$context
IContextSource $context
Definition: ContextSource.php:33
ContextSource\getConfig
getConfig()
Definition: ContextSource.php:63
CategoryViewer\shortList
static shortList( $articles, $articles_start_char)
Format a list of articles chunked by letter in a bullet list.
Definition: CategoryViewer.php:602
CategoryViewer\$gallery
ImageGalleryBase $gallery
Definition: CategoryViewer.php:75
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:40
HtmlArmor
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:30
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:152
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:37
ImageGalleryBase
Image gallery.
Definition: ImageGalleryBase.php:32
CategoryViewer\addFragmentToTitle
addFragmentToTitle( $title, $section)
Takes a title, and adds the fragment identifier that corresponds to the correct segment of the catego...
Definition: CategoryViewer.php:668
Category
Category objects are immutable, strictly speaking.
Definition: Category.php:32
CategoryViewer\columnList
static columnList( $articles, $articles_start_char)
Format a list of articles chunked by letter in a three-column list, ordered vertically.
Definition: CategoryViewer.php:561
CategoryViewer\getCountMessage
getCountMessage( $rescnt, $dbcnt, $type)
What to do if the category table conflicts with the number of results returned? This function says wh...
Definition: CategoryViewer.php:698
Title\getPrefixedText
getPrefixedText()
Get the prefixed title with spaces.
Definition: Title.php:1850
NS_FILE
const NS_FILE
Definition: Defines.php:75
CategoryViewer\getImageSection
getImageSection()
Definition: CategoryViewer.php:460
CategoryViewer\getPagesSection
getPagesSection()
Definition: CategoryViewer.php:430
CategoryViewer\getSubcategorySortChar
getSubcategorySortChar( $title, $sortkey)
Get the character to be used for sorting subcategories.
Definition: CategoryViewer.php:227
CategoryViewer\$articles
string[] $articles
Definition: CategoryViewer.php:39
ContextSource\getRequest
getRequest()
Definition: ContextSource.php:71
CategoryViewer\$imgsNoGallery_start_char
array $imgsNoGallery_start_char
Definition: CategoryViewer.php:54
$res
$res
Definition: testCompression.php:57
CategoryViewer\clearCategoryState
clearCategoryState()
Definition: CategoryViewer.php:156
LinkCache\getSelectFields
static getSelectFields()
Fields that LinkCache needs to select.
Definition: LinkCache.php:219
Collation
Definition: Collation.php:29
CategoryViewer\__construct
__construct( $title, IContextSource $context, $from=[], $until=[], $query=[])
Definition: CategoryViewer.php:92
CategoryViewer\formatList
formatList( $articles, $articles_start_char, $cutoff=6)
Format a list of articles chunked by letter, either as a bullet list or a columnar format,...
Definition: CategoryViewer.php:530
CategoryViewer\finaliseCategoryState
finaliseCategoryState()
Definition: CategoryViewer.php:276
CategoryViewer\doCategoryQuery
doCategoryQuery()
Definition: CategoryViewer.php:291
$dbr
$dbr
Definition: testCompression.php:54
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:128
Collation\singleton
static singleton()
Definition: Collation.php:36
CategoryViewer\$cat
Category $cat
Category object for this page.
Definition: CategoryViewer.php:78
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:315
CategoryViewer\getSectionPagingLinks
getSectionPagingLinks( $type)
Get the paging links for a section (subcats/pages/files), to go at the top and bottom of the output.
Definition: CategoryViewer.php:493
Title\getDBkey
getDBkey()
Get the main part with underscores.
Definition: Title.php:1023
MWException
MediaWiki exception.
Definition: MWException.php:28
CategoryViewer\$articles_start_char
array $articles_start_char
Definition: CategoryViewer.php:42
CategoryViewer\$imgsNoGallery
array $imgsNoGallery
Definition: CategoryViewer.php:57
Title\getNamespace
getNamespace()
Get the namespace index, i.e.
Definition: Title.php:1032
CategoryViewer\$collation
Collation $collation
Definition: CategoryViewer.php:72
Title\newFromRow
static newFromRow( $row)
Make a Title object from a DB row.
Definition: Title.php:524
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2461
Title\getCategorySortkey
getCategorySortkey( $prefix='')
Returns the raw sort key to be used for categories, with the specified prefix.
Definition: Title.php:4386
ContextSource\getOutput
getOutput()
Definition: ContextSource.php:112
ContextSource
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
Definition: ContextSource.php:29
CategoryViewer\$flip
array $flip
Definition: CategoryViewer.php:66
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:592
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
NS_CATEGORY
const NS_CATEGORY
Definition: Defines.php:83
CategoryViewer\addSubcategoryObject
addSubcategoryObject(Category $cat, $sortkey, $pageLength)
Add a subcategory to the internal lists, using a Category object.
Definition: CategoryViewer.php:184
ContextSource\setContext
setContext(IContextSource $context)
Definition: ContextSource.php:55
CategoryViewer\getCategoryBottom
getCategoryBottom()
Definition: CategoryViewer.php:516
CategoryViewer\$from
array $from
Definition: CategoryViewer.php:33
Category\newFromRow
static newFromRow( $row, $title=null)
Factory function, for constructing a Category object from a result set.
Definition: Category.php:186
CategoryViewer\getHTML
getHTML()
Format the category data list.
Definition: CategoryViewer.php:114
CategoryViewer\$prevPage
array $prevPage
Definition: CategoryViewer.php:63
Category\newFromTitle
static newFromTitle( $title)
Factory function.
Definition: Category.php:153
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:168
CategoryViewer
Definition: CategoryViewer.php:26
CategoryViewer\$title
Title $title
Definition: CategoryViewer.php:69
CategoryViewer\generateLink
generateLink( $type, Title $title, $isRedirect, $html=null)
Definition: CategoryViewer.php:199
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
Title
Represents a title within MediaWiki.
Definition: Title.php:42
Title\isRedirect
isRedirect( $flags=0)
Is this an article that is a redirect page? Uses link cache, adding it if necessary.
Definition: Title.php:3250
CategoryViewer\pagingLinks
pagingLinks( $first, $last, $type='')
Create paging links, as a helper method to getSectionPagingLinks().
Definition: CategoryViewer.php:626
IContextSource\getConfig
getConfig()
Get the site configuration.
Html\openElement
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:251
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
CategoryViewer\$limit
int $limit
Definition: CategoryViewer.php:30
CategoryViewer\$showGallery
bool $showGallery
Definition: CategoryViewer.php:51
CategoryViewer\getSubcategorySection
getSubcategorySection()
Definition: CategoryViewer.php:406
ImageGalleryBase\factory
static factory( $mode=false, IContextSource $context=null)
Get a new image gallery.
Definition: ImageGalleryBase.php:116
CategoryViewer\addPage
addPage( $title, $sortkey, $pageLength, $isRedirect=false)
Add a miscellaneous page.
Definition: CategoryViewer.php:269
CategoryViewer\$nextPage
array $nextPage
Definition: CategoryViewer.php:60
CategoryViewer\$children_start_char
array $children_start_char
Definition: CategoryViewer.php:48
CategoryViewer\getCategoryTop
getCategoryTop()
Definition: CategoryViewer.php:396
CategoryViewer\addImage
addImage(Title $title, $sortkey, $pageLength, $isRedirect=false)
Add a page in the image namespace.
Definition: CategoryViewer.php:246
Title\getText
getText()
Get the text form (spaces not underscores) of the main part.
Definition: Title.php:1005
$type
$type
Definition: testCompression.php:52
CategoryViewer\$until
array $until
Definition: CategoryViewer.php:36