MediaWiki  REL1_22
InfoAction.php
Go to the documentation of this file.
00001 <?php
00030 class InfoAction extends FormlessAction {
00031     const CACHE_VERSION = '2013-03-17';
00032 
00038     public function getName() {
00039         return 'info';
00040     }
00041 
00047     public function requiresUnblock() {
00048         return false;
00049     }
00050 
00056     public function requiresWrite() {
00057         return false;
00058     }
00059 
00066     public static function invalidateCache( Title $title ) {
00067         global $wgMemc;
00068         // Clear page info.
00069         $revision = WikiPage::factory( $title )->getRevision();
00070         if ( $revision !== null ) {
00071             $key = wfMemcKey( 'infoaction', sha1( $title->getPrefixedText() ), $revision->getId() );
00072             $wgMemc->delete( $key );
00073         }
00074     }
00075 
00081     public function onView() {
00082         $content = '';
00083 
00084         // Validate revision
00085         $oldid = $this->page->getOldID();
00086         if ( $oldid ) {
00087             $revision = $this->page->getRevisionFetched();
00088 
00089             // Revision is missing
00090             if ( $revision === null ) {
00091                 return $this->msg( 'missing-revision', $oldid )->parse();
00092             }
00093 
00094             // Revision is not current
00095             if ( !$revision->isCurrent() ) {
00096                 return $this->msg( 'pageinfo-not-current' )->plain();
00097             }
00098         }
00099 
00100         // Page header
00101         if ( !$this->msg( 'pageinfo-header' )->isDisabled() ) {
00102             $content .= $this->msg( 'pageinfo-header' )->parse();
00103         }
00104 
00105         // Hide "This page is a member of # hidden categories" explanation
00106         $content .= Html::element( 'style', array(),
00107             '.mw-hiddenCategoriesExplanation { display: none; }' ) . "\n";
00108 
00109         // Hide "Templates used on this page" explanation
00110         $content .= Html::element( 'style', array(),
00111             '.mw-templatesUsedExplanation { display: none; }' ) . "\n";
00112 
00113         // Get page information
00114         $pageInfo = $this->pageInfo();
00115 
00116         // Allow extensions to add additional information
00117         wfRunHooks( 'InfoAction', array( $this->getContext(), &$pageInfo ) );
00118 
00119         // Render page information
00120         foreach ( $pageInfo as $header => $infoTable ) {
00121             // Messages:
00122             // pageinfo-header-basic, pageinfo-header-edits, pageinfo-header-restrictions,
00123             // pageinfo-header-properties, pageinfo-category-info
00124             $content .= $this->makeHeader( $this->msg( "pageinfo-${header}" )->escaped() ) . "\n";
00125             $table = "\n";
00126             foreach ( $infoTable as $infoRow ) {
00127                 $name = ( $infoRow[0] instanceof Message ) ? $infoRow[0]->escaped() : $infoRow[0];
00128                 $value = ( $infoRow[1] instanceof Message ) ? $infoRow[1]->escaped() : $infoRow[1];
00129                 $id = ( $infoRow[0] instanceof Message ) ? $infoRow[0]->getKey() : null;
00130                 $table = $this->addRow( $table, $name, $value, $id ) . "\n";
00131             }
00132             $content = $this->addTable( $content, $table ) . "\n";
00133         }
00134 
00135         // Page footer
00136         if ( !$this->msg( 'pageinfo-footer' )->isDisabled() ) {
00137             $content .= $this->msg( 'pageinfo-footer' )->parse();
00138         }
00139 
00140         // Page credits
00141         /*if ( $this->page->exists() ) {
00142             $content .= Html::rawElement( 'div', array( 'id' => 'mw-credits' ), $this->getContributors() );
00143         }*/
00144 
00145         return $content;
00146     }
00147 
00154     protected function makeHeader( $header ) {
00155         $spanAttribs = array( 'class' => 'mw-headline', 'id' => Sanitizer::escapeId( $header ) );
00156         return Html::rawElement( 'h2', array(), Html::element( 'span', $spanAttribs, $header ) );
00157     }
00158 
00168     protected function addRow( $table, $name, $value, $id ) {
00169         return $table . Html::rawElement( 'tr', $id === null ? array() : array( 'id' => 'mw-' . $id ),
00170             Html::rawElement( 'td', array( 'style' => 'vertical-align: top;' ), $name ) .
00171             Html::rawElement( 'td', array(), $value )
00172         );
00173     }
00174 
00182     protected function addTable( $content, $table ) {
00183         return $content . Html::rawElement( 'table', array( 'class' => 'wikitable mw-page-info' ),
00184             $table );
00185     }
00186 
00194     protected function pageInfo() {
00195         global $wgContLang, $wgRCMaxAge, $wgMemc,
00196             $wgUnwatchedPageThreshold, $wgPageInfoTransclusionLimit;
00197 
00198         $user = $this->getUser();
00199         $lang = $this->getLanguage();
00200         $title = $this->getTitle();
00201         $id = $title->getArticleID();
00202 
00203         $memcKey = wfMemcKey( 'infoaction',
00204             sha1( $title->getPrefixedText() ), $this->page->getLatest() );
00205         $pageCounts = $wgMemc->get( $memcKey );
00206         $version = isset( $pageCounts['cacheversion'] ) ? $pageCounts['cacheversion'] : false;
00207         if ( $pageCounts === false || $version !== self::CACHE_VERSION ) {
00208             // Get page information that would be too "expensive" to retrieve by normal means
00209             $pageCounts = self::pageCounts( $title );
00210             $pageCounts['cacheversion'] = self::CACHE_VERSION;
00211 
00212             $wgMemc->set( $memcKey, $pageCounts );
00213         }
00214 
00215         // Get page properties
00216         $dbr = wfGetDB( DB_SLAVE );
00217         $result = $dbr->select(
00218             'page_props',
00219             array( 'pp_propname', 'pp_value' ),
00220             array( 'pp_page' => $id ),
00221             __METHOD__
00222         );
00223 
00224         $pageProperties = array();
00225         foreach ( $result as $row ) {
00226             $pageProperties[$row->pp_propname] = $row->pp_value;
00227         }
00228 
00229         // Basic information
00230         $pageInfo = array();
00231         $pageInfo['header-basic'] = array();
00232 
00233         // Display title
00234         $displayTitle = $title->getPrefixedText();
00235         if ( !empty( $pageProperties['displaytitle'] ) ) {
00236             $displayTitle = $pageProperties['displaytitle'];
00237         }
00238 
00239         $pageInfo['header-basic'][] = array(
00240             $this->msg( 'pageinfo-display-title' ), $displayTitle
00241         );
00242 
00243         // Is it a redirect? If so, where to?
00244         if ( $title->isRedirect() ) {
00245             $pageInfo['header-basic'][] = array(
00246                 $this->msg( 'pageinfo-redirectsto' ),
00247                 Linker::link( $this->page->getRedirectTarget() ) .
00248                 $this->msg( 'word-separator' )->text() .
00249                 $this->msg( 'parentheses', Linker::link(
00250                     $this->page->getRedirectTarget(),
00251                     $this->msg( 'pageinfo-redirectsto-info' )->escaped(),
00252                     array(),
00253                     array( 'action' => 'info' )
00254                 ) )->text()
00255             );
00256         }
00257 
00258         // Default sort key
00259         $sortKey = $title->getCategorySortkey();
00260         if ( !empty( $pageProperties['defaultsort'] ) ) {
00261             $sortKey = $pageProperties['defaultsort'];
00262         }
00263 
00264         $sortKey = htmlspecialchars( $sortKey );
00265         $pageInfo['header-basic'][] = array( $this->msg( 'pageinfo-default-sort' ), $sortKey );
00266 
00267         // Page length (in bytes)
00268         $pageInfo['header-basic'][] = array(
00269             $this->msg( 'pageinfo-length' ), $lang->formatNum( $title->getLength() )
00270         );
00271 
00272         // Page ID (number not localised, as it's a database ID)
00273         $pageInfo['header-basic'][] = array( $this->msg( 'pageinfo-article-id' ), $id );
00274 
00275         // Language in which the page content is (supposed to be) written
00276         $pageLang = $title->getPageLanguage()->getCode();
00277         $pageInfo['header-basic'][] = array( $this->msg( 'pageinfo-language' ),
00278             Language::fetchLanguageName( $pageLang, $lang->getCode() )
00279             . ' ' . $this->msg( 'parentheses', $pageLang ) );
00280 
00281         // Search engine status
00282         $pOutput = new ParserOutput();
00283         if ( isset( $pageProperties['noindex'] ) ) {
00284             $pOutput->setIndexPolicy( 'noindex' );
00285         }
00286 
00287         // Use robot policy logic
00288         $policy = $this->page->getRobotPolicy( 'view', $pOutput );
00289         $pageInfo['header-basic'][] = array(
00290             // Messages: pageinfo-robot-index, pageinfo-robot-noindex
00291             $this->msg( 'pageinfo-robot-policy' ), $this->msg( "pageinfo-robot-${policy['index']}" )
00292         );
00293 
00294         if ( isset( $pageCounts['views'] ) ) {
00295             // Number of views
00296             $pageInfo['header-basic'][] = array(
00297                 $this->msg( 'pageinfo-views' ), $lang->formatNum( $pageCounts['views'] )
00298             );
00299         }
00300 
00301         if (
00302             $user->isAllowed( 'unwatchedpages' ) ||
00303             ( $wgUnwatchedPageThreshold !== false &&
00304               $pageCounts['watchers'] >= $wgUnwatchedPageThreshold )
00305         ) {
00306             // Number of page watchers
00307             $pageInfo['header-basic'][] = array(
00308                 $this->msg( 'pageinfo-watchers' ), $lang->formatNum( $pageCounts['watchers'] )
00309             );
00310         } elseif ( $wgUnwatchedPageThreshold !== false ) {
00311             $pageInfo['header-basic'][] = array(
00312                 $this->msg( 'pageinfo-watchers' ),
00313                 $this->msg( 'pageinfo-few-watchers' )->numParams( $wgUnwatchedPageThreshold )
00314             );
00315         }
00316 
00317         // Redirects to this page
00318         $whatLinksHere = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() );
00319         $pageInfo['header-basic'][] = array(
00320             Linker::link(
00321                 $whatLinksHere,
00322                 $this->msg( 'pageinfo-redirects-name' )->escaped(),
00323                 array(),
00324                 array( 'hidelinks' => 1, 'hidetrans' => 1 )
00325             ),
00326             $this->msg( 'pageinfo-redirects-value' )
00327                 ->numParams( count( $title->getRedirectsHere() ) )
00328         );
00329 
00330         // Is it counted as a content page?
00331         if ( $this->page->isCountable() ) {
00332             $pageInfo['header-basic'][] = array(
00333                 $this->msg( 'pageinfo-contentpage' ),
00334                 $this->msg( 'pageinfo-contentpage-yes' )
00335             );
00336         }
00337 
00338         // Subpages of this page, if subpages are enabled for the current NS
00339         if ( MWNamespace::hasSubpages( $title->getNamespace() ) ) {
00340             $prefixIndex = SpecialPage::getTitleFor( 'Prefixindex', $title->getPrefixedText() . '/' );
00341             $pageInfo['header-basic'][] = array(
00342                 Linker::link( $prefixIndex, $this->msg( 'pageinfo-subpages-name' )->escaped() ),
00343                 $this->msg( 'pageinfo-subpages-value' )
00344                     ->numParams(
00345                         $pageCounts['subpages']['total'],
00346                         $pageCounts['subpages']['redirects'],
00347                         $pageCounts['subpages']['nonredirects'] )
00348             );
00349         }
00350 
00351         if ( $title->inNamespace( NS_CATEGORY ) ) {
00352             $category = Category::newFromTitle( $title );
00353             $pageInfo['category-info'] = array(
00354                 array(
00355                     $this->msg( 'pageinfo-category-pages' ),
00356                     $lang->formatNum( $category->getPageCount() )
00357                 ),
00358                 array(
00359                     $this->msg( 'pageinfo-category-subcats' ),
00360                     $lang->formatNum( $category->getSubcatCount() )
00361                 ),
00362                 array(
00363                     $this->msg( 'pageinfo-category-files' ),
00364                     $lang->formatNum( $category->getFileCount() )
00365                 )
00366             );
00367         }
00368 
00369         // Page protection
00370         $pageInfo['header-restrictions'] = array();
00371 
00372         // Is this page effected by the cascading protection of something which includes it?
00373         if ( $title->isCascadeProtected() ) {
00374             $cascadingFrom = '';
00375             $sources = $title->getCascadeProtectionSources(); // Array deferencing is in PHP 5.4 :(
00376 
00377             foreach ( $sources[0] as $sourceTitle ) {
00378                 $cascadingFrom .= Html::rawElement( 'li', array(), Linker::linkKnown( $sourceTitle ) );
00379             }
00380 
00381             $cascadingFrom = Html::rawElement( 'ul', array(), $cascadingFrom );
00382             $pageInfo['header-restrictions'][] = array(
00383                 $this->msg( 'pageinfo-protect-cascading-from' ),
00384                 $cascadingFrom
00385             );
00386         }
00387 
00388         // Is out protection set to cascade to other pages?
00389         if ( $title->areRestrictionsCascading() ) {
00390             $pageInfo['header-restrictions'][] = array(
00391                 $this->msg( 'pageinfo-protect-cascading' ),
00392                 $this->msg( 'pageinfo-protect-cascading-yes' )
00393             );
00394         }
00395 
00396         // Page protection
00397         foreach ( $title->getRestrictionTypes() as $restrictionType ) {
00398             $protectionLevel = implode( ', ', $title->getRestrictions( $restrictionType ) );
00399 
00400             if ( $protectionLevel == '' ) {
00401                 // Allow all users
00402                 $message = $this->msg( 'protect-default' )->escaped();
00403             } else {
00404                 // Administrators only
00405                 // Messages: protect-level-autoconfirmed, protect-level-sysop
00406                 $message = $this->msg( "protect-level-$protectionLevel" );
00407                 if ( $message->isDisabled() ) {
00408                     // Require "$1" permission
00409                     $message = $this->msg( "protect-fallback", $protectionLevel )->parse();
00410                 } else {
00411                     $message = $message->escaped();
00412                 }
00413             }
00414 
00415             // Messages: restriction-edit, restriction-move, restriction-create,
00416             // restriction-upload
00417             $pageInfo['header-restrictions'][] = array(
00418                 $this->msg( "restriction-$restrictionType" ), $message
00419             );
00420         }
00421 
00422         if ( !$this->page->exists() ) {
00423             return $pageInfo;
00424         }
00425 
00426         // Edit history
00427         $pageInfo['header-edits'] = array();
00428 
00429         $firstRev = $this->page->getOldestRevision();
00430         $lastRev = $this->page->getRevision();
00431         $batch = new LinkBatch;
00432 
00433         if ( $firstRev ) {
00434             $firstRevUser = $firstRev->getUserText( Revision::FOR_THIS_USER );
00435             if ( $firstRevUser !== '' ) {
00436                 $batch->add( NS_USER, $firstRevUser );
00437                 $batch->add( NS_USER_TALK, $firstRevUser );
00438             }
00439         }
00440 
00441         if ( $lastRev ) {
00442             $lastRevUser = $lastRev->getUserText( Revision::FOR_THIS_USER );
00443             if ( $lastRevUser !== '' ) {
00444                 $batch->add( NS_USER, $lastRevUser );
00445                 $batch->add( NS_USER_TALK, $lastRevUser );
00446             }
00447         }
00448 
00449         $batch->execute();
00450 
00451         if ( $firstRev ) {
00452             // Page creator
00453             $pageInfo['header-edits'][] = array(
00454                 $this->msg( 'pageinfo-firstuser' ),
00455                 Linker::revUserTools( $firstRev )
00456             );
00457 
00458             // Date of page creation
00459             $pageInfo['header-edits'][] = array(
00460                 $this->msg( 'pageinfo-firsttime' ),
00461                 Linker::linkKnown(
00462                     $title,
00463                     $lang->userTimeAndDate( $firstRev->getTimestamp(), $user ),
00464                     array(),
00465                     array( 'oldid' => $firstRev->getId() )
00466                 )
00467             );
00468         }
00469 
00470         if ( $lastRev ) {
00471             // Latest editor
00472             $pageInfo['header-edits'][] = array(
00473                 $this->msg( 'pageinfo-lastuser' ),
00474                 Linker::revUserTools( $lastRev )
00475             );
00476 
00477             // Date of latest edit
00478             $pageInfo['header-edits'][] = array(
00479                 $this->msg( 'pageinfo-lasttime' ),
00480                 Linker::linkKnown(
00481                     $title,
00482                     $lang->userTimeAndDate( $this->page->getTimestamp(), $user ),
00483                     array(),
00484                     array( 'oldid' => $this->page->getLatest() )
00485                 )
00486             );
00487         }
00488 
00489         // Total number of edits
00490         $pageInfo['header-edits'][] = array(
00491             $this->msg( 'pageinfo-edits' ), $lang->formatNum( $pageCounts['edits'] )
00492         );
00493 
00494         // Total number of distinct authors
00495         $pageInfo['header-edits'][] = array(
00496             $this->msg( 'pageinfo-authors' ), $lang->formatNum( $pageCounts['authors'] )
00497         );
00498 
00499         // Recent number of edits (within past 30 days)
00500         $pageInfo['header-edits'][] = array(
00501             $this->msg( 'pageinfo-recent-edits', $lang->formatDuration( $wgRCMaxAge ) ),
00502             $lang->formatNum( $pageCounts['recent_edits'] )
00503         );
00504 
00505         // Recent number of distinct authors
00506         $pageInfo['header-edits'][] = array(
00507             $this->msg( 'pageinfo-recent-authors' ), $lang->formatNum( $pageCounts['recent_authors'] )
00508         );
00509 
00510         // Array of MagicWord objects
00511         $magicWords = MagicWord::getDoubleUnderscoreArray();
00512 
00513         // Array of magic word IDs
00514         $wordIDs = $magicWords->names;
00515 
00516         // Array of IDs => localized magic words
00517         $localizedWords = $wgContLang->getMagicWords();
00518 
00519         $listItems = array();
00520         foreach ( $pageProperties as $property => $value ) {
00521             if ( in_array( $property, $wordIDs ) ) {
00522                 $listItems[] = Html::element( 'li', array(), $localizedWords[$property][1] );
00523             }
00524         }
00525 
00526         $localizedList = Html::rawElement( 'ul', array(), implode( '', $listItems ) );
00527         $hiddenCategories = $this->page->getHiddenCategories();
00528 
00529         if (
00530             count( $listItems ) > 0 ||
00531             count( $hiddenCategories ) > 0 ||
00532             $pageCounts['transclusion']['from'] > 0 ||
00533             $pageCounts['transclusion']['to'] > 0
00534         ) {
00535             $options = array( 'LIMIT' => $wgPageInfoTransclusionLimit );
00536             $transcludedTemplates = $title->getTemplateLinksFrom( $options );
00537             $transcludedTargets = $title->getTemplateLinksTo( $options );
00538 
00539             // Page properties
00540             $pageInfo['header-properties'] = array();
00541 
00542             // Magic words
00543             if ( count( $listItems ) > 0 ) {
00544                 $pageInfo['header-properties'][] = array(
00545                     $this->msg( 'pageinfo-magic-words' )->numParams( count( $listItems ) ),
00546                     $localizedList
00547                 );
00548             }
00549 
00550             // Hidden categories
00551             if ( count( $hiddenCategories ) > 0 ) {
00552                 $pageInfo['header-properties'][] = array(
00553                     $this->msg( 'pageinfo-hidden-categories' )
00554                         ->numParams( count( $hiddenCategories ) ),
00555                     Linker::formatHiddenCategories( $hiddenCategories )
00556                 );
00557             }
00558 
00559             // Transcluded templates
00560             if ( $pageCounts['transclusion']['from'] > 0 ) {
00561                 if ( $pageCounts['transclusion']['from'] > count( $transcludedTemplates ) ) {
00562                     $more = $this->msg( 'morenotlisted' )->escaped();
00563                 } else {
00564                     $more = null;
00565                 }
00566 
00567                 $pageInfo['header-properties'][] = array(
00568                     $this->msg( 'pageinfo-templates' )
00569                         ->numParams( $pageCounts['transclusion']['from'] ),
00570                     Linker::formatTemplates(
00571                         $transcludedTemplates,
00572                         false,
00573                         false,
00574                         $more )
00575                 );
00576             }
00577 
00578             if ( $pageCounts['transclusion']['to'] > 0 ) {
00579                 if ( $pageCounts['transclusion']['to'] > count( $transcludedTargets ) ) {
00580                     $more = Linker::link(
00581                         $whatLinksHere,
00582                         $this->msg( 'moredotdotdot' )->escaped(),
00583                         array(),
00584                         array( 'hidelinks' => 1, 'hideredirs' => 1 )
00585                     );
00586                 } else {
00587                     $more = null;
00588                 }
00589 
00590                 $pageInfo['header-properties'][] = array(
00591                     $this->msg( 'pageinfo-transclusions' )
00592                         ->numParams( $pageCounts['transclusion']['to'] ),
00593                     Linker::formatTemplates(
00594                         $transcludedTargets,
00595                         false,
00596                         false,
00597                         $more )
00598                 );
00599             }
00600         }
00601 
00602         return $pageInfo;
00603     }
00604 
00611     protected static function pageCounts( Title $title ) {
00612         global $wgRCMaxAge, $wgDisableCounters;
00613 
00614         wfProfileIn( __METHOD__ );
00615         $id = $title->getArticleID();
00616 
00617         $dbr = wfGetDB( DB_SLAVE );
00618         $result = array();
00619 
00620         if ( !$wgDisableCounters ) {
00621             // Number of views
00622             $views = (int)$dbr->selectField(
00623                 'page',
00624                 'page_counter',
00625                 array( 'page_id' => $id ),
00626                 __METHOD__
00627             );
00628             $result['views'] = $views;
00629         }
00630 
00631         // Number of page watchers
00632         $watchers = (int)$dbr->selectField(
00633             'watchlist',
00634             'COUNT(*)',
00635             array(
00636                 'wl_namespace' => $title->getNamespace(),
00637                 'wl_title' => $title->getDBkey(),
00638             ),
00639             __METHOD__
00640         );
00641         $result['watchers'] = $watchers;
00642 
00643         // Total number of edits
00644         $edits = (int)$dbr->selectField(
00645             'revision',
00646             'COUNT(rev_page)',
00647             array( 'rev_page' => $id ),
00648             __METHOD__
00649         );
00650         $result['edits'] = $edits;
00651 
00652         // Total number of distinct authors
00653         $authors = (int)$dbr->selectField(
00654             'revision',
00655             'COUNT(DISTINCT rev_user_text)',
00656             array( 'rev_page' => $id ),
00657             __METHOD__
00658         );
00659         $result['authors'] = $authors;
00660 
00661         // "Recent" threshold defined by $wgRCMaxAge
00662         $threshold = $dbr->timestamp( time() - $wgRCMaxAge );
00663 
00664         // Recent number of edits
00665         $edits = (int)$dbr->selectField(
00666             'revision',
00667             'COUNT(rev_page)',
00668             array(
00669                 'rev_page' => $id,
00670                 "rev_timestamp >= " . $dbr->addQuotes( $threshold )
00671             ),
00672             __METHOD__
00673         );
00674         $result['recent_edits'] = $edits;
00675 
00676         // Recent number of distinct authors
00677         $authors = (int)$dbr->selectField(
00678             'revision',
00679             'COUNT(DISTINCT rev_user_text)',
00680             array(
00681                 'rev_page' => $id,
00682                 "rev_timestamp >= " . $dbr->addQuotes( $threshold )
00683             ),
00684             __METHOD__
00685         );
00686         $result['recent_authors'] = $authors;
00687 
00688         // Subpages (if enabled)
00689         if ( MWNamespace::hasSubpages( $title->getNamespace() ) ) {
00690             $conds = array( 'page_namespace' => $title->getNamespace() );
00691             $conds[] = 'page_title ' . $dbr->buildLike( $title->getDBkey() . '/', $dbr->anyString() );
00692 
00693             // Subpages of this page (redirects)
00694             $conds['page_is_redirect'] = 1;
00695             $result['subpages']['redirects'] = (int)$dbr->selectField(
00696                 'page',
00697                 'COUNT(page_id)',
00698                 $conds,
00699                 __METHOD__ );
00700 
00701             // Subpages of this page (non-redirects)
00702             $conds['page_is_redirect'] = 0;
00703             $result['subpages']['nonredirects'] = (int)$dbr->selectField(
00704                 'page',
00705                 'COUNT(page_id)',
00706                 $conds,
00707                 __METHOD__
00708             );
00709 
00710             // Subpages of this page (total)
00711             $result['subpages']['total'] = $result['subpages']['redirects']
00712                 + $result['subpages']['nonredirects'];
00713         }
00714 
00715         // Counts for the number of transclusion links (to/from)
00716         $result['transclusion']['to'] = (int)$dbr->selectField(
00717             'templatelinks',
00718             'COUNT(tl_from)',
00719             array(
00720                 'tl_namespace' => $title->getNamespace(),
00721                 'tl_title' => $title->getDBkey()
00722             ),
00723             __METHOD__
00724         );
00725 
00726         $result['transclusion']['from'] = (int)$dbr->selectField(
00727             'templatelinks',
00728             'COUNT(*)',
00729             array( 'tl_from' => $title->getArticleID() ),
00730             __METHOD__
00731         );
00732 
00733         wfProfileOut( __METHOD__ );
00734         return $result;
00735     }
00736 
00742     protected function getPageTitle() {
00743         return $this->msg( 'pageinfo-title', $this->getTitle()->getPrefixedText() )->text();
00744     }
00745 
00750     protected function getContributors() {
00751         global $wgHiddenPrefs;
00752 
00753         $contributors = $this->page->getContributors();
00754         $real_names = array();
00755         $user_names = array();
00756         $anon_ips = array();
00757 
00758         # Sift for real versus user names
00759         foreach ( $contributors as $user ) {
00760             $page = $user->isAnon()
00761                 ? SpecialPage::getTitleFor( 'Contributions', $user->getName() )
00762                 : $user->getUserPage();
00763 
00764             if ( $user->getID() == 0 ) {
00765                 $anon_ips[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
00766             } elseif ( !in_array( 'realname', $wgHiddenPrefs ) && $user->getRealName() ) {
00767                 $real_names[] = Linker::link( $page, htmlspecialchars( $user->getRealName() ) );
00768             } else {
00769                 $user_names[] = Linker::link( $page, htmlspecialchars( $user->getName() ) );
00770             }
00771         }
00772 
00773         $lang = $this->getLanguage();
00774 
00775         $real = $lang->listToText( $real_names );
00776 
00777         # "ThisSite user(s) A, B and C"
00778         if ( count( $user_names ) ) {
00779             $user = $this->msg( 'siteusers' )->rawParams( $lang->listToText( $user_names ) )->params(
00780                 count( $user_names ) )->escaped();
00781         } else {
00782             $user = false;
00783         }
00784 
00785         if ( count( $anon_ips ) ) {
00786             $anon = $this->msg( 'anonusers' )->rawParams( $lang->listToText( $anon_ips ) )->params(
00787                 count( $anon_ips ) )->escaped();
00788         } else {
00789             $anon = false;
00790         }
00791 
00792         # This is the big list, all mooshed together. We sift for blank strings
00793         $fulllist = array();
00794         foreach ( array( $real, $user, $anon ) as $s ) {
00795             if ( $s !== '' ) {
00796                 array_push( $fulllist, $s );
00797             }
00798         }
00799 
00800         $count = count( $fulllist );
00801         # "Based on work by ..."
00802         return $count
00803             ? $this->msg( 'othercontribs' )->rawParams(
00804                 $lang->listToText( $fulllist ) )->params( $count )->escaped()
00805             : '';
00806     }
00807 
00813     protected function getDescription() {
00814         return '';
00815     }
00816 }