MediaWiki REL1_31
CategoryTree.php
Go to the documentation of this file.
1<?php
30 public $mOptions = [];
31
35 public function __construct( $options ) {
36 global $wgCategoryTreeDefaultOptions;
37
38 // ensure default values and order of options.
39 // Order may become important, it may influence the cache key!
40 foreach ( $wgCategoryTreeDefaultOptions as $option => $default ) {
41 if ( isset( $options[$option] ) ) {
42 $this->mOptions[$option] = $options[$option];
43 } else {
44 $this->mOptions[$option] = $default;
45 }
46 }
47
48 $this->mOptions['mode'] = self::decodeMode( $this->mOptions['mode'] );
49
50 if ( $this->mOptions['mode'] == CategoryTreeMode::PARENTS ) {
51 // namespace filter makes no sense with CategoryTreeMode::PARENTS
52 $this->mOptions['namespaces'] = false;
53 }
54
55 $this->mOptions['hideprefix'] = self::decodeHidePrefix( $this->mOptions['hideprefix'] );
56 $this->mOptions['showcount'] = self::decodeBoolean( $this->mOptions['showcount'] );
57 $this->mOptions['namespaces'] = self::decodeNamespaces( $this->mOptions['namespaces'] );
58
59 if ( $this->mOptions['namespaces'] ) {
60 # automatically adjust mode to match namespace filter
61 if ( count( $this->mOptions['namespaces'] ) === 1
62 && $this->mOptions['namespaces'][0] == NS_CATEGORY ) {
63 $this->mOptions['mode'] = CategoryTreeMode::CATEGORIES;
64 } elseif ( !in_array( NS_FILE, $this->mOptions['namespaces'] ) ) {
65 $this->mOptions['mode'] = CategoryTreeMode::PAGES;
66 } else {
67 $this->mOptions['mode'] = CategoryTreeMode::ALL;
68 }
69 }
70 }
71
76 public function getOption( $name ) {
77 return $this->mOptions[$name];
78 }
79
83 private function isInverse() {
84 return $this->getOption( 'mode' ) == CategoryTreeMode::PARENTS;
85 }
86
91 private static function decodeNamespaces( $nn ) {
92 global $wgContLang;
93
94 if ( $nn === false || is_null( $nn ) ) {
95 return false;
96 }
97
98 if ( !is_array( $nn ) ) {
99 $nn = preg_split( '![\s#:|]+!', $nn );
100 }
101
102 $namespaces = [];
103
104 foreach ( $nn as $n ) {
105 if ( is_int( $n ) ) {
106 $ns = $n;
107 } else {
108 $n = trim( $n );
109 if ( $n === '' ) {
110 continue;
111 }
112
113 $lower = strtolower( $n );
114
115 if ( is_numeric( $n ) ) {
116 $ns = (int)$n;
117 } elseif ( $n == '-' || $n == '_' || $n == '*' || $lower == 'main' ) {
118 $ns = NS_MAIN;
119 } else {
120 $ns = $wgContLang->getNsIndex( $n );
121 }
122 }
123
124 if ( is_int( $ns ) ) {
125 $namespaces[] = $ns;
126 }
127 }
128
129 sort( $namespaces ); # get elements into canonical order
130 return $namespaces;
131 }
132
137 public static function decodeMode( $mode ) {
138 global $wgCategoryTreeDefaultOptions;
139
140 if ( is_null( $mode ) ) {
141 return $wgCategoryTreeDefaultOptions['mode'];
142 }
143 if ( is_int( $mode ) ) {
144 return $mode;
145 }
146
147 $mode = trim( strtolower( $mode ) );
148
149 if ( is_numeric( $mode ) ) {
150 return (int)$mode;
151 }
152
153 if ( $mode == 'all' ) {
154 $mode = CategoryTreeMode::ALL;
155 } elseif ( $mode == 'pages' ) {
157 } elseif ( $mode == 'categories' || $mode == 'sub' ) {
159 } elseif ( $mode == 'parents' || $mode == 'super' || $mode == 'inverse' ) {
161 } elseif ( $mode == 'default' ) {
162 $mode = $wgCategoryTreeDefaultOptions['mode'];
163 }
164
165 return (int)$mode;
166 }
167
174 public static function decodeBoolean( $value ) {
175 if ( is_null( $value ) ) {
176 return null;
177 }
178 if ( is_bool( $value ) ) {
179 return $value;
180 }
181 if ( is_int( $value ) ) {
182 return ( $value > 0 );
183 }
184
185 $value = trim( strtolower( $value ) );
186 if ( is_numeric( $value ) ) {
187 return ( (int)$value > 0 );
188 }
189
190 if ( $value == 'yes' || $value == 'y'
191 || $value == 'true' || $value == 't' || $value == 'on'
192 ) {
193 return true;
194 } elseif ( $value == 'no' || $value == 'n'
195 || $value == 'false' || $value == 'f' || $value == 'off'
196 ) {
197 return false;
198 } elseif ( $value == 'null' || $value == 'default' || $value == 'none' || $value == 'x' ) {
199 return null;
200 } else {
201 return false;
202 }
203 }
204
209 public static function decodeHidePrefix( $value ) {
210 global $wgCategoryTreeDefaultOptions;
211
212 if ( is_null( $value ) ) {
213 return $wgCategoryTreeDefaultOptions['hideprefix'];
214 }
215 if ( is_int( $value ) ) {
216 return $value;
217 }
218 if ( $value === true ) {
220 }
221 if ( $value === false ) {
223 }
224
225 $value = trim( strtolower( $value ) );
226
227 if ( $value == 'yes' || $value == 'y'
228 || $value == 'true' || $value == 't' || $value == 'on'
229 ) {
231 } elseif ( $value == 'no' || $value == 'n'
232 || $value == 'false' || $value == 'f' || $value == 'off'
233 ) {
235 } elseif ( $value == 'always' ) {
237 } elseif ( $value == 'never' ) {
239 } elseif ( $value == 'auto' ) {
241 } elseif ( $value == 'categories' || $value == 'category' || $value == 'smart' ) {
243 } else {
244 return $wgCategoryTreeDefaultOptions['hideprefix'];
245 }
246 }
247
252 public static function setHeaders( $outputPage ) {
253 # Add the modules
254 $outputPage->addModuleStyles( 'ext.categoryTree.css' );
255 $outputPage->addModules( 'ext.categoryTree' );
256 }
257
264 protected static function encodeOptions( $options, $enc ) {
265 if ( $enc == 'mode' || $enc == '' ) {
266 $opt = $options['mode'];
267 } elseif ( $enc == 'json' ) {
268 $opt = FormatJson::encode( $options );
269 } else {
270 throw new Exception( 'Unknown encoding for CategoryTree options: ' . $enc );
271 }
272
273 return $opt;
274 }
275
280 public function getOptionsAsCacheKey( $depth = null ) {
281 $key = "";
282
283 foreach ( $this->mOptions as $k => $v ) {
284 if ( is_array( $v ) ) {
285 $v = implode( '|', $v );
286 }
287 $key .= $k . ':' . $v . ';';
288 }
289
290 if ( !is_null( $depth ) ) {
291 $key .= ";depth=" . $depth;
292 }
293 return $key;
294 }
295
300 public function getOptionsAsJsStructure( $depth = null ) {
301 if ( $depth !== null ) {
303 $opt['depth'] = $depth;
304 $s = self::encodeOptions( $opt, 'json' );
305 } else {
306 $s = self::encodeOptions( $this->mOptions, 'json' );
307 }
308
309 return $s;
310 }
311
315 private function getOptionsAsUrlParameters() {
316 return http_build_query( $this->mOptions );
317 }
318
330 public function getTag( $parser, $category, $hideroot = false, $attr = [], $depth = 1,
331 $allowMissing = false
332 ) {
333 global $wgCategoryTreeDisableCache;
334
335 $category = trim( $category );
336 if ( $category === '' ) {
337 return false;
338 }
339
340 if ( $parser ) {
341 if ( $wgCategoryTreeDisableCache === true ) {
342 $parser->disableCache();
343 } elseif ( is_int( $wgCategoryTreeDisableCache ) ) {
344 $parser->getOutput()->updateCacheExpiry( $wgCategoryTreeDisableCache );
345 }
346 }
347
348 $title = self::makeTitle( $category );
349
350 if ( $title === false || $title === null ) {
351 return false;
352 }
353
354 if ( isset( $attr['class'] ) ) {
355 $attr['class'] .= ' CategoryTreeTag';
356 } else {
357 $attr['class'] = ' CategoryTreeTag';
358 }
359
360 $attr['data-ct-mode'] = $this->mOptions['mode'];
361 $attr['data-ct-options'] = $this->getOptionsAsJsStructure();
362
363 $html = '';
364 $html .= Html::openElement( 'div', $attr );
365
366 if ( !$allowMissing && !$title->getArticleID() ) {
367 $html .= Html::openElement( 'span', [ 'class' => 'CategoryTreeNotice' ] );
368 if ( $parser ) {
369 $html .= $parser->recursiveTagParse(
370 wfMessage( 'categorytree-not-found', $category )->plain() );
371 } else {
372 $html .= wfMessage( 'categorytree-not-found', $category )->parse();
373 }
374 $html .= Html::closeElement( 'span' );
375 } else {
376 if ( !$hideroot ) {
377 $html .= $this->renderNode( $title, $depth );
378 } else {
379 $html .= $this->renderChildren( $title, $depth );
380 }
381 }
382
383 $html .= Xml::closeElement( 'div' );
384 $html .= "\n\t\t";
385
386 return $html;
387 }
388
395 public function renderChildren( $title, $depth = 1 ) {
396 global $wgCategoryTreeMaxChildren, $wgCategoryTreeUseCategoryTable;
397
398 if ( $title->getNamespace() != NS_CATEGORY ) {
399 // Non-categories can't have children. :)
400 return '';
401 }
402
404
405 $inverse = $this->isInverse();
406 $mode = $this->getOption( 'mode' );
407 $namespaces = $this->getOption( 'namespaces' );
408
409 $tables = [ 'page', 'categorylinks' ];
410 $fields = [ 'page_id', 'page_namespace', 'page_title',
411 'page_is_redirect', 'page_len', 'page_latest', 'cl_to',
412 'cl_from' ];
413 $where = [];
414 $joins = [];
415 $options = [ 'ORDER BY' => 'cl_type, cl_sortkey', 'LIMIT' => $wgCategoryTreeMaxChildren ];
416
417 if ( $inverse ) {
418 $joins['categorylinks'] = [ 'RIGHT JOIN', [
419 'cl_to = page_title', 'page_namespace' => NS_CATEGORY
420 ] ];
421 $where['cl_from'] = $title->getArticleID();
422 } else {
423 $joins['categorylinks'] = [ 'JOIN', 'cl_from = page_id' ];
424 $where['cl_to'] = $title->getDBkey();
425 $options['USE INDEX']['categorylinks'] = 'cl_sortkey';
426
427 # namespace filter.
428 if ( $namespaces ) {
429 // NOTE: we assume that the $namespaces array contains only integers!
430 // decodeNamepsaces makes it so.
431 $where['page_namespace'] = $namespaces;
432 } elseif ( $mode != CategoryTreeMode::ALL ) {
433 if ( $mode == CategoryTreeMode::PAGES ) {
434 $where['cl_type'] = [ 'page', 'subcat' ];
435 } else {
436 $where['cl_type'] = 'subcat';
437 }
438 }
439 }
440
441 # fetch member count if possible
442 $doCount = !$inverse && $wgCategoryTreeUseCategoryTable;
443
444 if ( $doCount ) {
445 $tables = array_merge( $tables, [ 'category' ] );
446 $fields = array_merge( $fields, [
447 'cat_id', 'cat_title', 'cat_subcats', 'cat_pages', 'cat_files'
448 ] );
449 $joins['category'] = [ 'LEFT JOIN', [
450 'cat_title = page_title', 'page_namespace' => NS_CATEGORY ]
451 ];
452 }
453
454 $res = $dbr->select( $tables, $fields, $where, __METHOD__, $options, $joins );
455
456 # collect categories separately from other pages
457 $categories = '';
458 $other = '';
459
460 foreach ( $res as $row ) {
461 # NOTE: in inverse mode, the page record may be null, because we use a right join.
462 # happens for categories with no category page (red cat links)
463 if ( $inverse && $row->page_title === null ) {
464 $t = Title::makeTitle( NS_CATEGORY, $row->cl_to );
465 } else {
466 # TODO: translation support; ideally added to Title object
467 $t = Title::newFromRow( $row );
468 }
469
470 $cat = null;
471
472 if ( $doCount && $row->page_namespace == NS_CATEGORY ) {
473 $cat = Category::newFromRow( $row, $t );
474 }
475
476 $s = $this->renderNodeInfo( $t, $cat, $depth - 1 );
477 $s .= "\n\t\t";
478
479 if ( $row->page_namespace == NS_CATEGORY ) {
480 $categories .= $s;
481 } else {
482 $other .= $s;
483 }
484 }
485
486 return $categories . $other;
487 }
488
494 public function renderParents( $title ) {
495 global $wgCategoryTreeMaxChildren;
496
498
499 $res = $dbr->select(
500 'categorylinks',
501 [
502 'page_namespace' => NS_CATEGORY,
503 'page_title' => 'cl_to',
504 ],
505 [ 'cl_from' => $title->getArticleID() ],
506 __METHOD__,
507 [
508 'LIMIT' => $wgCategoryTreeMaxChildren,
509 'ORDER BY' => 'cl_to'
510 ]
511 );
512
513 $special = SpecialPage::getTitleFor( 'CategoryTree' );
514
515 $s = '';
516
517 foreach ( $res as $row ) {
518 $t = Title::newFromRow( $row );
519
520 $label = $t->getText();
521
522 $wikiLink = $special->getLocalURL( 'target=' . $t->getPartialURL() .
523 '&' . $this->getOptionsAsUrlParameters() );
524
525 if ( $s !== '' ) {
526 $s .= wfMessage( 'pipe-separator' )->escaped();
527 }
528
529 $s .= Xml::openElement( 'span', [ 'class' => 'CategoryTreeItem' ] );
530 $s .= Xml::element( 'a', [ 'class' => 'CategoryTreeLabel', 'href' => $wikiLink ], $label );
531 $s .= Xml::closeElement( 'span' );
532
533 $s .= "\n\t\t";
534 }
535
536 return $s;
537 }
538
545 public function renderNode( $title, $children = 0 ) {
546 global $wgCategoryTreeUseCategoryTable;
547
548 if ( $wgCategoryTreeUseCategoryTable && $title->getNamespace() == NS_CATEGORY
549 && !$this->isInverse()
550 ) {
551 $cat = Category::newFromTitle( $title );
552 } else {
553 $cat = null;
554 }
555
556 return $this->renderNodeInfo( $title, $cat, $children );
557 }
558
567 public function renderNodeInfo( $title, $cat, $children = 0 ) {
568 $mode = $this->getOption( 'mode' );
569
570 $ns = $title->getNamespace();
571 $key = $title->getDBkey();
572
573 $hideprefix = $this->getOption( 'hideprefix' );
574
575 if ( $hideprefix == CategoryTreeHidePrefix::ALWAYS ) {
576 $hideprefix = true;
577 } elseif ( $hideprefix == CategoryTreeHidePrefix::AUTO ) {
578 $hideprefix = ( $mode == CategoryTreeMode::CATEGORIES );
579 } elseif ( $hideprefix == CategoryTreeHidePrefix::CATEGORIES ) {
580 $hideprefix = ( $ns == NS_CATEGORY );
581 } else {
582 $hideprefix = true;
583 }
584
585 // when showing only categories, omit namespace in label unless we explicitely defined the
586 // configuration setting
587 // patch contributed by Manuel Schneider <manuel.schneider@wikimedia.ch>, Bug 8011
588 if ( $hideprefix ) {
589 $label = $title->getText();
590 } else {
591 $label = $title->getPrefixedText();
592 }
593
594 $labelClass = 'CategoryTreeLabel ' . ' CategoryTreeLabelNs' . $ns;
595
596 if ( !$title->getArticleID() ) {
597 $labelClass .= ' new';
598 $wikiLink = $title->getLocalURL( 'action=edit&redlink=1' );
599 } else {
600 $wikiLink = $title->getLocalURL();
601 }
602
603 if ( $ns == NS_CATEGORY ) {
604 $labelClass .= ' CategoryTreeLabelCategory';
605 } else {
606 $labelClass .= ' CategoryTreeLabelPage';
607 }
608
609 if ( ( $ns % 2 ) > 0 ) {
610 $labelClass .= ' CategoryTreeLabelTalk';
611 }
612
613 $count = false;
614 $s = '';
615
616 # NOTE: things in CategoryTree.js rely on the exact order of tags!
617 # Specifically, the CategoryTreeChildren div must be the first
618 # sibling with nodeName = DIV of the grandparent of the expland link.
619
620 $s .= Xml::openElement( 'div', [ 'class' => 'CategoryTreeSection' ] );
621 $s .= Xml::openElement( 'div', [ 'class' => 'CategoryTreeItem' ] );
622
623 $attr = [ 'class' => 'CategoryTreeBullet' ];
624
625 if ( $ns == NS_CATEGORY ) {
626 if ( $cat ) {
627 if ( $mode == CategoryTreeMode::CATEGORIES ) {
628 $count = intval( $cat->getSubcatCount() );
629 } elseif ( $mode == CategoryTreeMode::PAGES ) {
630 $count = intval( $cat->getPageCount() ) - intval( $cat->getFileCount() );
631 } else {
632 $count = intval( $cat->getPageCount() );
633 }
634 }
635 if ( $count === 0 ) {
636 $bullet = wfMessage( 'categorytree-empty-bullet' )->escaped() . ' ';
637 $attr['class'] = 'CategoryTreeEmptyBullet';
638 } else {
639 $linkattr = [];
640
641 $linkattr[ 'class' ] = "CategoryTreeToggle";
642 $linkattr['data-ct-title'] = $key;
643
644 $tag = 'span';
645 if ( $children == 0 ) {
646 // Use ->plain() and htmlspecialchars() to ensure
647 // identical to what is done by JS, which does:
648 // $link.text( mw.msg( 'categorytree-expand-bullet' ) )
649 $txt = htmlspecialchars( wfMessage( 'categorytree-expand-bullet' )->plain() );
650 $linkattr[ 'data-ct-state' ] = 'collapsed';
651 } else {
652 $txt = htmlspecialchars( wfMessage( 'categorytree-collapse-bullet' )->plain() );
653 $linkattr[ 'data-ct-loaded' ] = true;
654 $linkattr[ 'data-ct-state' ] = 'expanded';
655 }
656
657 $bullet = Xml::openElement( $tag, $linkattr ) . $txt . Xml::closeElement( $tag ) . ' ';
658 }
659 } else {
660 $bullet = wfMessage( 'categorytree-page-bullet' )->escaped();
661 }
662 $s .= Xml::tags( 'span', $attr, $bullet ) . ' ';
663
664 $s .= Xml::element(
665 'a',
666 [
667 'class' => $labelClass,
668 'href' => $wikiLink,
669 'title' => $title->getPrefixedText()
670 ],
671 $label
672 );
673
674 if ( $count !== false && $this->getOption( 'showcount' ) ) {
676 }
677
678 $s .= Xml::closeElement( 'div' );
679 $s .= "\n\t\t";
680 $s .= Xml::openElement(
681 'div',
682 [
683 'class' => 'CategoryTreeChildren',
684 'style' => $children > 0 ? "display:block" : "display:none"
685 ]
686 );
687
688 if ( $ns == NS_CATEGORY && $children > 0 ) {
689 $children = $this->renderChildren( $title, $children );
690 if ( $children == '' ) {
691 $s .= Xml::openElement( 'i', [ 'class' => 'CategoryTreeNotice' ] );
692 if ( $mode == CategoryTreeMode::CATEGORIES ) {
693 $s .= wfMessage( 'categorytree-no-subcategories' )->escaped();
694 } elseif ( $mode == CategoryTreeMode::PAGES ) {
695 $s .= wfMessage( 'categorytree-no-pages' )->escaped();
696 } elseif ( $mode == CategoryTreeMode::PARENTS ) {
697 $s .= wfMessage( 'categorytree-no-parent-categories' )->escaped();
698 } else {
699 $s .= wfMessage( 'categorytree-nothing-found' )->escaped();
700 }
701 $s .= Xml::closeElement( 'i' );
702 } else {
703 $s .= $children;
704 }
705 }
706
707 $s .= Xml::closeElement( 'div' );
708 $s .= Xml::closeElement( 'div' );
709
710 $s .= "\n\t\t";
711
712 return $s;
713 }
714
722 public static function createCountString( IContextSource $context, $cat, $countMode ) {
723 global $wgContLang;
724
725 # Get counts, with conversion to integer so === works
726 # Note: $allCount is the total number of cat members,
727 # not the count of how many members are normal pages.
728 $allCount = $cat ? intval( $cat->getPageCount() ) : 0;
729 $subcatCount = $cat ? intval( $cat->getSubcatCount() ) : 0;
730 $fileCount = $cat ? intval( $cat->getFileCount() ) : 0;
731 $pages = $allCount - $subcatCount - $fileCount;
732
733 $attr = [
734 'title' => $context->msg( 'categorytree-member-counts' )
735 ->numParams( $subcatCount, $pages, $fileCount, $allCount, $countMode )->text(),
736 'dir' => $context->getLanguage()->getDir() # numbers and commas get messed up in a mixed dir env
737 ];
738
739 $s = $wgContLang->getDirMark() . ' ';
740
741 # Create a list of category members with only non-zero member counts
742 $memberNums = [];
743 if ( $subcatCount ) {
744 $memberNums[] = $context->msg( 'categorytree-num-categories' )
745 ->numParams( $subcatCount )->text();
746 }
747 if ( $pages ) {
748 $memberNums[] = $context->msg( 'categorytree-num-pages' )->numParams( $pages )->text();
749 }
750 if ( $fileCount ) {
751 $memberNums[] = $context->msg( 'categorytree-num-files' )
752 ->numParams( $fileCount )->text();
753 }
754 $memberNumsShort = $memberNums
755 ? $context->getLanguage()->commaList( $memberNums )
756 : $context->msg( 'categorytree-num-empty' )->text();
757
758 # Only $5 is actually used in the default message.
759 # Other arguments can be used in a customized message.
760 $s .= Xml::tags(
761 'span',
762 $attr,
763 $context->msg( 'categorytree-member-num' )
764 // Do not use numParams on params 1-4, as they are only used for customisation.
765 ->params( $subcatCount, $pages, $fileCount, $allCount, $memberNumsShort )
766 ->escaped()
767 );
768
769 return $s;
770 }
771
777 public static function makeTitle( $title ) {
778 $title = trim( $title );
779
780 if ( strval( $title ) === '' ) {
781 return null;
782 }
783
784 # The title must be in the category namespace
785 # Ignore a leading Category: if there is one
786 $t = Title::newFromText( $title, NS_CATEGORY );
787 if ( !$t || $t->getNamespace() != NS_CATEGORY || $t->getInterwiki() != '' ) {
788 // If we were given something like "Wikipedia:Foo" or "Template:",
789 // try it again but forced.
790 $title = "Category:$title";
791 $t = Title::newFromText( $title );
792 }
793 return $t;
794 }
795
802 public static function capDepth( $mode, $depth ) {
803 global $wgCategoryTreeMaxDepth;
804
805 if ( is_numeric( $depth ) ) {
806 $depth = intval( $depth );
807 } else {
808 return 1;
809 }
810
811 if ( is_array( $wgCategoryTreeMaxDepth ) ) {
812 $max = isset( $wgCategoryTreeMaxDepth[$mode] ) ? $wgCategoryTreeMaxDepth[$mode] : 1;
813 } elseif ( is_numeric( $wgCategoryTreeMaxDepth ) ) {
814 $max = $wgCategoryTreeMaxDepth;
815 } else {
816 wfDebug( 'CategoryTree::capDepth: $wgCategoryTreeMaxDepth is invalid.' );
817 $max = 1;
818 }
819
820 return min( $depth, $max );
821 }
822}
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Core functions for the CategoryTree extension, an AJAX based gadget to display the category structure...
static encodeOptions( $options, $enc)
renderParents( $title)
Returns a string with an HTML representation of the parents of the given category.
renderNodeInfo( $title, $cat, $children=0)
Returns a string with a HTML represenation of the given page.
renderNode( $title, $children=0)
Returns a string with a HTML represenation of the given page.
__construct( $options)
static decodeBoolean( $value)
Helper function to convert a string to a boolean value.
static decodeHidePrefix( $value)
static decodeMode( $mode)
getTag( $parser, $category, $hideroot=false, $attr=[], $depth=1, $allowMissing=false)
Custom tag implementation.
renderChildren( $title, $depth=1)
Returns a string with an HTML representation of the children of the given category.
getOptionsAsCacheKey( $depth=null)
getOption( $name)
static decodeNamespaces( $nn)
static makeTitle( $title)
Creates a Title object from a user provided (and thus unsafe) string.
static capDepth( $mode, $depth)
Internal function to cap depth.
getOptionsAsJsStructure( $depth=null)
static setHeaders( $outputPage)
Add ResourceLoader modules to the OutputPage object.
static createCountString(IContextSource $context, $cat, $countMode)
Create a string which format the page, subcat and file counts of a category.
static getMain()
Get the RequestContext object associated with the main request.
$res
Definition database.txt:21
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add in any order
Definition design.txt:19
do that in ParserLimitReportFormat instead $parser
Definition hooks.txt:2603
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
Definition hooks.txt:1015
namespace and then decline to actually register it & $namespaces
Definition hooks.txt:934
either a plain
Definition hooks.txt:2056
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition hooks.txt:2001
do that in ParserLimitReportFormat instead use this to modify the parameters of the image all existing parser cache entries will be invalid To avoid you ll need to handle that somehow(e.g. with the RejectParserCacheValue hook) because MediaWiki won 't do it for you. & $defaults also a ContextSource after deleting those rows but within the same transaction you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
Definition hooks.txt:2811
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt;div ...>$1&lt;/div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition hooks.txt:2013
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
const NS_FILE
Definition Defines.php:80
const NS_MAIN
Definition Defines.php:74
const NS_CATEGORY
Definition Defines.php:88
Interface for objects which can provide a MediaWiki context on request.
const DB_REPLICA
Definition defines.php:25