MediaWiki
REL1_22
|
00001 <?php 00031 class SpecialVersion extends SpecialPage { 00032 00033 protected $firstExtOpened = false; 00034 00035 protected static $extensionTypes = false; 00036 00037 protected static $viewvcUrls = array( 00038 'svn+ssh://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', 00039 'http://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', 00040 'https://svn.wikimedia.org/svnroot/mediawiki' => 'https://svn.wikimedia.org/viewvc/mediawiki', 00041 ); 00042 00043 public function __construct() { 00044 parent::__construct( 'Version' ); 00045 } 00046 00050 public function execute( $par ) { 00051 global $wgSpecialVersionShowHooks, $IP; 00052 00053 $this->setHeaders(); 00054 $this->outputHeader(); 00055 $out = $this->getOutput(); 00056 $out->allowClickjacking(); 00057 00058 if ( $par !== 'Credits' ) { 00059 $text = 00060 $this->getMediaWikiCredits() . 00061 $this->softwareInformation() . 00062 $this->getEntryPointInfo() . 00063 $this->getExtensionCredits(); 00064 if ( $wgSpecialVersionShowHooks ) { 00065 $text .= $this->getWgHooks(); 00066 } 00067 00068 $out->addWikiText( $text ); 00069 $out->addHTML( $this->IPInfo() ); 00070 00071 if ( $this->getRequest()->getVal( 'easteregg' ) ) { 00072 // TODO: put something interesting here 00073 } 00074 } else { 00075 // Credits sub page 00076 00077 // Header 00078 $out->addHTML( wfMessage( 'version-credits-summary' )->parseAsBlock() ); 00079 00080 $wikiText = file_get_contents( $IP . '/CREDITS' ); 00081 00082 // Take everything from the first section onwards, to remove the (not localized) header 00083 $wikiText = substr( $wikiText, strpos( $wikiText, '==' ) ); 00084 00085 $out->addWikiText( $wikiText ); 00086 } 00087 } 00088 00094 private static function getMediaWikiCredits() { 00095 $ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMessage( 'version-license' )->text() ); 00096 00097 // This text is always left-to-right. 00098 $ret .= '<div class="plainlinks">'; 00099 $ret .= "__NOTOC__ 00100 " . self::getCopyrightAndAuthorList() . "\n 00101 " . wfMessage( 'version-license-info' )->text(); 00102 $ret .= '</div>'; 00103 00104 return str_replace( "\t\t", '', $ret ) . "\n"; 00105 } 00106 00112 public static function getCopyrightAndAuthorList() { 00113 global $wgLang; 00114 00115 if ( defined( 'MEDIAWIKI_INSTALL' ) ) { 00116 $othersLink = '[//www.mediawiki.org/wiki/Special:Version/Credits ' . wfMessage( 'version-poweredby-others' )->text() . ']'; 00117 } else { 00118 $othersLink = '[[Special:Version/Credits|' . wfMessage( 'version-poweredby-others' )->text() . ']]'; 00119 } 00120 00121 $translatorsLink = '[//translatewiki.net/wiki/Translating:MediaWiki/Credits ' . wfMessage( 'version-poweredby-translators' )->text() . ']'; 00122 00123 $authorList = array( 00124 'Magnus Manske', 'Brion Vibber', 'Lee Daniel Crocker', 00125 'Tim Starling', 'Erik Möller', 'Gabriel Wicke', 'Ævar Arnfjörð Bjarmason', 00126 'Niklas Laxström', 'Domas Mituzas', 'Rob Church', 'Yuri Astrakhan', 00127 'Aryeh Gregor', 'Aaron Schulz', 'Andrew Garrett', 'Raimond Spekking', 00128 'Alexandre Emsenhuber', 'Siebrand Mazeland', 'Chad Horohoe', 00129 'Roan Kattouw', 'Trevor Parscal', 'Bryan Tong Minh', 'Sam Reed', 00130 'Victor Vasiliev', 'Rotem Liss', 'Platonides', 'Antoine Musso', 00131 'Timo Tijhof', 'Daniel Kinzler', 'Jeroen De Dauw', $othersLink, 00132 $translatorsLink 00133 ); 00134 00135 return wfMessage( 'version-poweredby-credits', MWTimestamp::getLocalInstance()->format( 'Y' ), 00136 $wgLang->listToText( $authorList ) )->text(); 00137 } 00138 00144 static function softwareInformation() { 00145 $dbr = wfGetDB( DB_SLAVE ); 00146 00147 // Put the software in an array of form 'name' => 'version'. All messages should 00148 // be loaded here, so feel free to use wfMessage in the 'name'. Raw HTML or 00149 // wikimarkup can be used. 00150 $software = array(); 00151 $software['[https://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked(); 00152 $software['[http://www.php.net/ PHP]'] = phpversion() . " (" . PHP_SAPI . ")"; 00153 $software[$dbr->getSoftwareLink()] = $dbr->getServerInfo(); 00154 00155 // Allow a hook to add/remove items. 00156 wfRunHooks( 'SoftwareInfo', array( &$software ) ); 00157 00158 $out = Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMessage( 'version-software' )->text() ) . 00159 Xml::openElement( 'table', array( 'class' => 'wikitable plainlinks', 'id' => 'sv-software' ) ) . 00160 "<tr> 00161 <th>" . wfMessage( 'version-software-product' )->text() . "</th> 00162 <th>" . wfMessage( 'version-software-version' )->text() . "</th> 00163 </tr>\n"; 00164 00165 foreach ( $software as $name => $version ) { 00166 $out .= "<tr> 00167 <td>" . $name . "</td> 00168 <td dir=\"ltr\">" . $version . "</td> 00169 </tr>\n"; 00170 } 00171 00172 return $out . Xml::closeElement( 'table' ); 00173 } 00174 00181 public static function getVersion( $flags = '' ) { 00182 global $wgVersion, $IP; 00183 wfProfileIn( __METHOD__ ); 00184 00185 $gitInfo = self::getGitHeadSha1( $IP ); 00186 $svnInfo = self::getSvnInfo( $IP ); 00187 if ( !$svnInfo && !$gitInfo ) { 00188 $version = $wgVersion; 00189 } elseif ( $gitInfo && $flags === 'nodb' ) { 00190 $shortSha1 = substr( $gitInfo, 0, 7 ); 00191 $version = "$wgVersion ($shortSha1)"; 00192 } elseif ( $gitInfo ) { 00193 $shortSha1 = substr( $gitInfo, 0, 7 ); 00194 $shortSha1 = wfMessage( 'parentheses' )->params( $shortSha1 )->escaped(); 00195 $version = "$wgVersion $shortSha1"; 00196 } elseif ( $flags === 'nodb' ) { 00197 $version = "$wgVersion (r{$svnInfo['checkout-rev']})"; 00198 } else { 00199 $version = $wgVersion . ' ' . 00200 wfMessage( 00201 'version-svn-revision', 00202 isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', 00203 $info['checkout-rev'] 00204 )->text(); 00205 } 00206 00207 wfProfileOut( __METHOD__ ); 00208 return $version; 00209 } 00210 00219 public static function getVersionLinked() { 00220 global $wgVersion; 00221 wfProfileIn( __METHOD__ ); 00222 00223 $gitVersion = self::getVersionLinkedGit(); 00224 if ( $gitVersion ) { 00225 $v = $gitVersion; 00226 } else { 00227 $svnVersion = self::getVersionLinkedSvn(); 00228 if ( $svnVersion ) { 00229 $v = $svnVersion; 00230 } else { 00231 $v = $wgVersion; // fallback 00232 } 00233 } 00234 00235 wfProfileOut( __METHOD__ ); 00236 return $v; 00237 } 00238 00242 private static function getVersionLinkedSvn() { 00243 global $IP; 00244 00245 $info = self::getSvnInfo( $IP ); 00246 if ( !isset( $info['checkout-rev'] ) ) { 00247 return false; 00248 } 00249 00250 $linkText = wfMessage( 00251 'version-svn-revision', 00252 isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', 00253 $info['checkout-rev'] 00254 )->text(); 00255 00256 if ( isset( $info['viewvc-url'] ) ) { 00257 $version = "[{$info['viewvc-url']} $linkText]"; 00258 } else { 00259 $version = $linkText; 00260 } 00261 00262 return self::getwgVersionLinked() . " $version"; 00263 } 00264 00268 private static function getwgVersionLinked() { 00269 global $wgVersion; 00270 $versionUrl = ""; 00271 if ( wfRunHooks( 'SpecialVersionVersionUrl', array( $wgVersion, &$versionUrl ) ) ) { 00272 $versionParts = array(); 00273 preg_match( "/^(\d+\.\d+)/", $wgVersion, $versionParts ); 00274 $versionUrl = "https://www.mediawiki.org/wiki/MediaWiki_{$versionParts[1]}"; 00275 } 00276 return "[$versionUrl $wgVersion]"; 00277 } 00278 00283 private static function getVersionLinkedGit() { 00284 global $IP, $wgLang; 00285 00286 $gitInfo = new GitInfo( $IP ); 00287 $headSHA1 = $gitInfo->getHeadSHA1(); 00288 if ( !$headSHA1 ) { 00289 return false; 00290 } 00291 00292 $shortSHA1 = '(' . substr( $headSHA1, 0, 7 ) . ')'; 00293 00294 $gitHeadUrl = $gitInfo->getHeadViewUrl(); 00295 if ( $gitHeadUrl !== false ) { 00296 $shortSHA1 = "[$gitHeadUrl $shortSHA1]"; 00297 } 00298 00299 $gitHeadCommitDate = $gitInfo->getHeadCommitDate(); 00300 if ( $gitHeadCommitDate ) { 00301 $shortSHA1 .= "<br/>" . $wgLang->timeanddate( $gitHeadCommitDate, true ); 00302 } 00303 00304 return self::getwgVersionLinked() . " $shortSHA1"; 00305 } 00306 00319 public static function getExtensionTypes() { 00320 if ( self::$extensionTypes === false ) { 00321 self::$extensionTypes = array( 00322 'specialpage' => wfMessage( 'version-specialpages' )->text(), 00323 'parserhook' => wfMessage( 'version-parserhooks' )->text(), 00324 'variable' => wfMessage( 'version-variables' )->text(), 00325 'media' => wfMessage( 'version-mediahandlers' )->text(), 00326 'antispam' => wfMessage( 'version-antispam' )->text(), 00327 'skin' => wfMessage( 'version-skins' )->text(), 00328 'api' => wfMessage( 'version-api' )->text(), 00329 'other' => wfMessage( 'version-other' )->text(), 00330 ); 00331 00332 wfRunHooks( 'ExtensionTypes', array( &self::$extensionTypes ) ); 00333 } 00334 00335 return self::$extensionTypes; 00336 } 00337 00347 public static function getExtensionTypeName( $type ) { 00348 $types = self::getExtensionTypes(); 00349 return isset( $types[$type] ) ? $types[$type] : $types['other']; 00350 } 00351 00357 function getExtensionCredits() { 00358 global $wgExtensionCredits, $wgExtensionFunctions, $wgParser; 00359 00360 if ( !count( $wgExtensionCredits ) && !count( $wgExtensionFunctions ) ) { 00361 return ''; 00362 } 00363 00364 $extensionTypes = self::getExtensionTypes(); 00365 00369 wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) ); 00370 00371 $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), $this->msg( 'version-extensions' )->text() ) . 00372 Xml::openElement( 'table', array( 'class' => 'wikitable plainlinks', 'id' => 'sv-ext' ) ); 00373 00374 // Make sure the 'other' type is set to an array. 00375 if ( !array_key_exists( 'other', $wgExtensionCredits ) ) { 00376 $wgExtensionCredits['other'] = array(); 00377 } 00378 00379 // Find all extensions that do not have a valid type and give them the type 'other'. 00380 foreach ( $wgExtensionCredits as $type => $extensions ) { 00381 if ( !array_key_exists( $type, $extensionTypes ) ) { 00382 $wgExtensionCredits['other'] = array_merge( $wgExtensionCredits['other'], $extensions ); 00383 } 00384 } 00385 00386 // Loop through the extension categories to display their extensions in the list. 00387 foreach ( $extensionTypes as $type => $message ) { 00388 if ( $type != 'other' ) { 00389 $out .= $this->getExtensionCategory( $type, $message ); 00390 } 00391 } 00392 00393 // We want the 'other' type to be last in the list. 00394 $out .= $this->getExtensionCategory( 'other', $extensionTypes['other'] ); 00395 00396 $tags = $wgParser->getTags(); 00397 $cnt = count( $tags ); 00398 00399 if ( $cnt ) { 00400 for ( $i = 0; $i < $cnt; ++$i ) { 00401 $tags[$i] = "<{$tags[$i]}>"; 00402 } 00403 $out .= $this->openExtType( $this->msg( 'version-parser-extensiontags' )->text(), 'parser-tags' ); 00404 $out .= '<tr><td colspan="4">' . $this->listToText( $tags ) . "</td></tr>\n"; 00405 } 00406 00407 $fhooks = $wgParser->getFunctionHooks(); 00408 if ( count( $fhooks ) ) { 00409 $out .= $this->openExtType( $this->msg( 'version-parser-function-hooks' )->text(), 'parser-function-hooks' ); 00410 $out .= '<tr><td colspan="4">' . $this->listToText( $fhooks ) . "</td></tr>\n"; 00411 } 00412 00413 $out .= Xml::closeElement( 'table' ); 00414 00415 return $out; 00416 } 00417 00428 protected function getExtensionCategory( $type, $message ) { 00429 global $wgExtensionCredits; 00430 00431 $out = ''; 00432 00433 if ( array_key_exists( $type, $wgExtensionCredits ) && count( $wgExtensionCredits[$type] ) > 0 ) { 00434 $out .= $this->openExtType( $message, 'credits-' . $type ); 00435 00436 usort( $wgExtensionCredits[$type], array( $this, 'compare' ) ); 00437 00438 foreach ( $wgExtensionCredits[$type] as $extension ) { 00439 $out .= $this->getCreditsForExtension( $extension ); 00440 } 00441 } 00442 00443 return $out; 00444 } 00445 00452 function compare( $a, $b ) { 00453 if ( $a['name'] === $b['name'] ) { 00454 return 0; 00455 } else { 00456 return $this->getLanguage()->lc( $a['name'] ) > $this->getLanguage()->lc( $b['name'] ) 00457 ? 1 00458 : -1; 00459 } 00460 } 00461 00469 function getCreditsForExtension( array $extension ) { 00470 global $wgLang; 00471 00472 $name = isset( $extension['name'] ) ? $extension['name'] : '[no name]'; 00473 00474 $vcsText = false; 00475 00476 if ( isset( $extension['path'] ) ) { 00477 $gitInfo = new GitInfo( dirname( $extension['path'] ) ); 00478 $gitHeadSHA1 = $gitInfo->getHeadSHA1(); 00479 if ( $gitHeadSHA1 !== false ) { 00480 $vcsText = '(' . substr( $gitHeadSHA1, 0, 7 ) . ')'; 00481 $gitViewerUrl = $gitInfo->getHeadViewUrl(); 00482 if ( $gitViewerUrl !== false ) { 00483 $vcsText = "[$gitViewerUrl $vcsText]"; 00484 } 00485 $gitHeadCommitDate = $gitInfo->getHeadCommitDate(); 00486 if ( $gitHeadCommitDate ) { 00487 $vcsText .= "<br/>" . $wgLang->timeanddate( $gitHeadCommitDate, true ); 00488 } 00489 } else { 00490 $svnInfo = self::getSvnInfo( dirname( $extension['path'] ) ); 00491 # Make subversion text/link. 00492 if ( $svnInfo !== false ) { 00493 $directoryRev = isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : null; 00494 $vcsText = $this->msg( 'version-svn-revision', $directoryRev, $svnInfo['checkout-rev'] )->text(); 00495 $vcsText = isset( $svnInfo['viewvc-url'] ) ? '[' . $svnInfo['viewvc-url'] . " $vcsText]" : $vcsText; 00496 } 00497 } 00498 } 00499 00500 # Make main link (or just the name if there is no URL). 00501 if ( isset( $extension['url'] ) ) { 00502 $mainLink = "[{$extension['url']} $name]"; 00503 } else { 00504 $mainLink = $name; 00505 } 00506 00507 if ( isset( $extension['version'] ) ) { 00508 $versionText = '<span class="mw-version-ext-version">' . 00509 $this->msg( 'version-version', $extension['version'] )->text() . 00510 '</span>'; 00511 } else { 00512 $versionText = ''; 00513 } 00514 00515 # Make description text. 00516 $description = isset( $extension['description'] ) ? $extension['description'] : ''; 00517 00518 if ( isset( $extension['descriptionmsg'] ) ) { 00519 # Look for a localized description. 00520 $descriptionMsg = $extension['descriptionmsg']; 00521 00522 if ( is_array( $descriptionMsg ) ) { 00523 $descriptionMsgKey = $descriptionMsg[0]; // Get the message key 00524 array_shift( $descriptionMsg ); // Shift out the message key to get the parameters only 00525 array_map( "htmlspecialchars", $descriptionMsg ); // For sanity 00526 $description = $this->msg( $descriptionMsgKey, $descriptionMsg )->text(); 00527 } else { 00528 $description = $this->msg( $descriptionMsg )->text(); 00529 } 00530 } 00531 00532 if ( $vcsText !== false ) { 00533 $extNameVer = "<tr> 00534 <td><em>$mainLink $versionText</em></td> 00535 <td><em>$vcsText</em></td>"; 00536 } else { 00537 $extNameVer = "<tr> 00538 <td colspan=\"2\"><em>$mainLink $versionText</em></td>"; 00539 } 00540 00541 $author = isset( $extension['author'] ) ? $extension['author'] : array(); 00542 $extDescAuthor = "<td>$description</td> 00543 <td>" . $this->listAuthors( $author, false ) . "</td> 00544 </tr>\n"; 00545 00546 return $extNameVer . $extDescAuthor; 00547 } 00548 00554 private function getWgHooks() { 00555 global $wgHooks; 00556 00557 if ( count( $wgHooks ) ) { 00558 $myWgHooks = $wgHooks; 00559 ksort( $myWgHooks ); 00560 00561 $ret = Xml::element( 'h2', array( 'id' => 'mw-version-hooks' ), $this->msg( 'version-hooks' )->text() ) . 00562 Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-hooks' ) ) . 00563 "<tr> 00564 <th>" . $this->msg( 'version-hook-name' )->text() . "</th> 00565 <th>" . $this->msg( 'version-hook-subscribedby' )->text() . "</th> 00566 </tr>\n"; 00567 00568 foreach ( $myWgHooks as $hook => $hooks ) { 00569 $ret .= "<tr> 00570 <td>$hook</td> 00571 <td>" . $this->listToText( $hooks ) . "</td> 00572 </tr>\n"; 00573 } 00574 00575 $ret .= Xml::closeElement( 'table' ); 00576 return $ret; 00577 } else { 00578 return ''; 00579 } 00580 } 00581 00582 private function openExtType( $text, $name = null ) { 00583 $opt = array( 'colspan' => 4 ); 00584 $out = ''; 00585 00586 if ( $this->firstExtOpened ) { 00587 // Insert a spacing line 00588 $out .= '<tr class="sv-space">' . Html::element( 'td', $opt ) . "</tr>\n"; 00589 } 00590 $this->firstExtOpened = true; 00591 00592 if ( $name ) { 00593 $opt['id'] = "sv-$name"; 00594 } 00595 00596 $out .= "<tr>" . Xml::element( 'th', $opt, $text ) . "</tr>\n"; 00597 00598 return $out; 00599 } 00600 00606 private function IPInfo() { 00607 $ip = str_replace( '--', ' - ', htmlspecialchars( $this->getRequest()->getIP() ) ); 00608 return "<!-- visited from $ip -->\n<span style='display:none'>visited from $ip</span>"; 00609 } 00610 00617 function listAuthors( $authors ) { 00618 $list = array(); 00619 foreach ( (array)$authors as $item ) { 00620 if ( $item == '...' ) { 00621 $list[] = $this->msg( 'version-poweredby-others' )->text(); 00622 } elseif ( substr( $item, -5 ) == ' ...]' ) { 00623 $list[] = substr( $item, 0, -4 ) . $this->msg( 'version-poweredby-others' )->text() . "]"; 00624 } else { 00625 $list[] = $item; 00626 } 00627 } 00628 return $this->listToText( $list, false ); 00629 } 00630 00639 function listToText( $list, $sort = true ) { 00640 $cnt = count( $list ); 00641 00642 if ( $cnt == 1 ) { 00643 // Enforce always returning a string 00644 return (string)self::arrayToString( $list[0] ); 00645 } elseif ( $cnt == 0 ) { 00646 return ''; 00647 } else { 00648 if ( $sort ) { 00649 sort( $list ); 00650 } 00651 return $this->getLanguage()->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) ); 00652 } 00653 } 00654 00663 public static function arrayToString( $list ) { 00664 if ( is_array( $list ) && count( $list ) == 1 ) { 00665 $list = $list[0]; 00666 } 00667 if ( is_object( $list ) ) { 00668 $class = wfMessage( 'parentheses' )->params( get_class( $list ) )->escaped(); 00669 return $class; 00670 } elseif ( !is_array( $list ) ) { 00671 return $list; 00672 } else { 00673 if ( is_object( $list[0] ) ) { 00674 $class = get_class( $list[0] ); 00675 } else { 00676 $class = $list[0]; 00677 } 00678 return wfMessage( 'parentheses' )->params( "$class, {$list[1]}" )->escaped(); 00679 } 00680 } 00681 00698 public static function getSvnInfo( $dir ) { 00699 // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html 00700 $entries = $dir . '/.svn/entries'; 00701 00702 if ( !file_exists( $entries ) ) { 00703 return false; 00704 } 00705 00706 $lines = file( $entries ); 00707 if ( !count( $lines ) ) { 00708 return false; 00709 } 00710 00711 // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4) 00712 if ( preg_match( '/^<\?xml/', $lines[0] ) ) { 00713 // subversion is release <= 1.3 00714 if ( !function_exists( 'simplexml_load_file' ) ) { 00715 // We could fall back to expat... YUCK 00716 return false; 00717 } 00718 00719 // SimpleXml whines about the xmlns... 00720 wfSuppressWarnings(); 00721 $xml = simplexml_load_file( $entries ); 00722 wfRestoreWarnings(); 00723 00724 if ( $xml ) { 00725 foreach ( $xml->entry as $entry ) { 00726 if ( $xml->entry[0]['name'] == '' ) { 00727 // The directory entry should always have a revision marker. 00728 if ( $entry['revision'] ) { 00729 return array( 'checkout-rev' => intval( $entry['revision'] ) ); 00730 } 00731 } 00732 } 00733 } 00734 00735 return false; 00736 } 00737 00738 // Subversion is release 1.4 or above. 00739 if ( count( $lines ) < 11 ) { 00740 return false; 00741 } 00742 00743 $info = array( 00744 'checkout-rev' => intval( trim( $lines[3] ) ), 00745 'url' => trim( $lines[4] ), 00746 'repo-url' => trim( $lines[5] ), 00747 'directory-rev' => intval( trim( $lines[10] ) ) 00748 ); 00749 00750 if ( isset( self::$viewvcUrls[$info['repo-url']] ) ) { 00751 $viewvc = str_replace( 00752 $info['repo-url'], 00753 self::$viewvcUrls[$info['repo-url']], 00754 $info['url'] 00755 ); 00756 00757 $viewvc .= '/?pathrev='; 00758 $viewvc .= urlencode( $info['checkout-rev'] ); 00759 $info['viewvc-url'] = $viewvc; 00760 } 00761 00762 return $info; 00763 } 00764 00772 public static function getSvnRevision( $dir ) { 00773 $info = self::getSvnInfo( $dir ); 00774 00775 if ( $info === false ) { 00776 return false; 00777 } elseif ( isset( $info['checkout-rev'] ) ) { 00778 return $info['checkout-rev']; 00779 } else { 00780 return false; 00781 } 00782 } 00783 00788 public static function getGitHeadSha1( $dir ) { 00789 $repo = new GitInfo( $dir ); 00790 return $repo->getHeadSHA1(); 00791 } 00792 00797 public function getEntryPointInfo() { 00798 global $wgArticlePath, $wgScriptPath; 00799 $scriptPath = $wgScriptPath ? $wgScriptPath : "/"; 00800 $entryPoints = array( 00801 'version-entrypoints-articlepath' => $wgArticlePath, 00802 'version-entrypoints-scriptpath' => $scriptPath, 00803 'version-entrypoints-index-php' => wfScript( 'index' ), 00804 'version-entrypoints-api-php' => wfScript( 'api' ), 00805 'version-entrypoints-load-php' => wfScript( 'load' ), 00806 ); 00807 00808 $language = $this->getLanguage(); 00809 $thAttribures = array( 00810 'dir' => $language->getDir(), 00811 'lang' => $language->getCode() 00812 ); 00813 $out = Html::element( 'h2', array( 'id' => 'mw-version-entrypoints' ), $this->msg( 'version-entrypoints' )->text() ) . 00814 Html::openElement( 'table', 00815 array( 00816 'class' => 'wikitable plainlinks', 00817 'id' => 'mw-version-entrypoints-table', 00818 'dir' => 'ltr', 00819 'lang' => 'en' 00820 ) 00821 ) . 00822 Html::openElement( 'tr' ) . 00823 Html::element( 'th', $thAttribures, $this->msg( 'version-entrypoints-header-entrypoint' )->text() ) . 00824 Html::element( 'th', $thAttribures, $this->msg( 'version-entrypoints-header-url' )->text() ) . 00825 Html::closeElement( 'tr' ); 00826 00827 foreach ( $entryPoints as $message => $value ) { 00828 $url = wfExpandUrl( $value, PROTO_RELATIVE ); 00829 $out .= Html::openElement( 'tr' ) . 00830 // ->text() looks like it should be ->parse(), but this function 00831 // returns wikitext, not HTML, boo 00832 Html::rawElement( 'td', array(), $this->msg( $message )->text() ) . 00833 Html::rawElement( 'td', array(), Html::rawElement( 'code', array(), "[$url $value]" ) ) . 00834 Html::closeElement( 'tr' ); 00835 } 00836 00837 $out .= Html::closeElement( 'table' ); 00838 return $out; 00839 } 00840 00841 protected function getGroupName() { 00842 return 'wiki'; 00843 } 00844 00845 }