X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fspecials%2FSpecialVersion.php;h=13db183eaac45939cf40b749393a536a08c94837;hb=b5e5f482ecb9b6bb60930c3f1034e33d5d4b04e4;hp=9c6748365d47d56b8d625e9e52f00cc8a55bc8a9;hpb=a8020fb61826be2b17404cb34fa32e6ba8c6a330;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/specials/SpecialVersion.php b/includes/specials/SpecialVersion.php index 9c6748365d..13db183eaa 100644 --- a/includes/specials/SpecialVersion.php +++ b/includes/specials/SpecialVersion.php @@ -1,5 +1,22 @@ 'http://svn.wikimedia.org/viewvc/mediawiki', + 'http://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', + # Doesn't work at the time of writing but maybe some day: + 'https://svn.wikimedia.org/viewvc/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki', + ); + + public function __construct(){ + parent::__construct( 'Version' ); } /** * main() */ - function execute( $par ) { - global $wgOut, $wgMessageCache, $wgSpecialVersionShowHooks, $wgContLang; - $wgMessageCache->loadAllMessages(); - + public function execute( $par ) { + global $wgOut, $wgSpecialVersionShowHooks, $wgContLang; + $this->setHeaders(); $this->outputHeader(); - if( $wgContLang->isRTL() ) { - $wgOut->addHTML( '
' ); - } else { - $wgOut->addHTML( '
' ); - } + $wgOut->addHTML( Xml::openElement( 'div', + array( 'dir' => $wgContLang->getDir() ) ) ); $text = - $this->MediaWikiCredits() . + $this->getMediaWikiCredits() . $this->softwareInformation() . - $this->extensionCredits(); + $this->getExtensionCredits(); if ( $wgSpecialVersionShowHooks ) { - $text .= $this->wgHooks(); + $text .= $this->getWgHooks(); } + $wgOut->addWikiText( $text ); $wgOut->addHTML( $this->IPInfo() ); $wgOut->addHTML( '
' ); } /** - * execuate command for output - * @param string command - * @return string output - */ - static function execOutput( $cmd ) { - $out = array( $cmd ); - exec( $cmd.' 2>&1', $out ); - unset($out[0]); - return implode("\n", $out ); - } - - /**#@+ - * @private - */ - - /** - * @return wiki text showing the license information + * Returns wiki text showing the license information. + * + * @return string */ - static function MediaWikiCredits() { - global $wgContLang; - + private static function getMediaWikiCredits() { $ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMsg( 'version-license' ) ); // This text is always left-to-right. $ret .= '
'; $ret .= "__NOTOC__ This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''', - copyright © 2001-2009 Magnus Manske, Brion Vibber, Lee Daniel Crocker, + copyright © 2001-2010 Magnus Manske, Brion Vibber, Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, Niklas Laxström, Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, - Aaron Schulz and others. + Aaron Schulz, Andrew Garrett, Raimond Spekking, Alexandre Emsenhuber, + Siebrand Mazeland, Chad Horohoe and others. MediaWiki is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -97,179 +106,22 @@ class SpecialVersion extends SpecialPage { } /** - * @return wiki text showing the third party software versions (apache, php, mysql). + * Returns wiki text showing the third party software versions (apache, php, mysql). + * + * @return string */ static function softwareInformation() { - global $wgUseImageMagick, $wgImageMagickConvertCommand, $wgDiff3, $wgDiff, $wgUseTeX; - global $wgAllowTitlesInSVG, $wgSVGConverter, $wgSVGConverters, $wgSVGConverterPath; $dbr = wfGetDB( DB_SLAVE ); // Put the software in an array of form 'name' => 'version'. All messages should // be loaded here, so feel free to use wfMsg*() in the 'name'. Raw HTML or wikimarkup - // can be used + // can be used. $software = array(); $software['[http://www.mediawiki.org/ MediaWiki]'] = self::getVersionLinked(); $software['[http://www.php.net/ PHP]'] = phpversion() . " (" . php_sapi_name() . ")"; $software[$dbr->getSoftwareLink()] = $dbr->getServerVersion(); - // Version information for diff3 - if ( file_exists( trim( $wgDiff3, '"' ) ) ) { - $swDiff3Info = self::execOutput( $wgDiff3 . ' -v' ); - $swDiff3Line = explode("\n",$swDiff3Info ,2); - $swDiff3Ver = $swDiff3Line[0]; - $swDiff3Ver = str_replace( 'diff3 (GNU diffutils) ', '' , $swDiff3Ver); - $software['[http://www.gnu.org/software/diffutils/diffutils.html diff3]'] = $swDiff3Ver; - } - - // Version information for diff - if ( file_exists( trim( $wgDiff, '"' ) ) ) { - $swDiffInfo = self::execOutput( $wgDiff . ' -v' ); - $swDiffLine = explode("\n",$swDiffInfo ,2); - $swDiffVer = $swDiffLine[0]; - $swDiffVer = str_replace( 'diff (GNU diffutils) ', '' , $swDiffVer); - $software['[http://www.gnu.org/software/diffutils/diffutils.html diff]'] = $swDiffVer; - } - - // Look for ImageMagick's version, if did not found, try to find the GD library version - if ( $wgUseImageMagick ) { - if ( file_exists( trim( $wgImageMagickConvertCommand, '"' ) ) ) { - $swImageMagickInfo = self::execOutput( $wgImageMagickConvertCommand . ' -version' ); - list( $head, $tail ) = explode( 'ImageMagick', $swImageMagickInfo ); - list( $swImageMagickVer ) = explode('http://www.imagemagick.org', $tail ); - $software['[http://www.imagemagick.org/ ImageMagick]'] = $swImageMagickVer; - } - } else { - if( function_exists( 'gd_info' ) ) { - $gdInfo = gd_info(); - if ( strstr( $gdInfo['GD Version'], 'bundled' ) != false ) { - $gd_URL = 'http://www.php.net/gd'; - } - else { - $gd_URL = 'http://www.libgd.org'; - } - $software['[' . $gd_URL . ' GD library]'] = $gdInfo['GD Version']; - } - } - - // Look for SVG converter and print the version info - if ( $wgAllowTitlesInSVG ) { - $swSVGConvName = $wgSVGConverter; - $haveSVGConvVer = false; - $pathVar = '$path/'; - $binPath = '/usr/bin/'; - $execPath = strtok(strstr($wgSVGConverters[$wgSVGConverter],$pathVar), ' '); - $execPath = substr_replace($execPath, '', 0, strlen($pathVar)); - $execFullPath = trim($wgSVGConverterPath,'"') . $execPath; - $execBinPath = $binPath . $execPath; - if (strstr($execFullPath, ' ') != false) { - $execFullPath = '"' . $execFullPath . '"'; - } - if ( !strcmp( $wgSVGConverter, 'ImageMagick') ) { - // Get version info for ImageMagick - if ( file_exists( $execBinPath ) ) - $swSVGConvInfo = self::execOutput( $execBinPath . ' -version' ); - else if ( file_exists( trim( $execFullPath, '"' ) ) || ( file_exists( trim( $execFullPath, '"' ) . '.exe' ) ) ) - $swSVGConvInfo = self::execOutput( $execFullPath . ' -version' ); - list( $head, $tail ) = explode( 'ImageMagick', $swSVGConvInfo ); - list( $swSVGConvVer ) = explode('http://www.imagemagick.org', $tail ); - $swSVGConvURL = 'http://www.imagemagick.org/'; - $haveSVGConvVer = true; - } else if ( strstr ($execFullPath, 'rsvg') != false ) { - // Get version info for rsvg - if ( file_exists( $execBinPath ) ) - $swSVGConvInfo = self::execOutput( $execBinPath . ' -v' ); - else if ( file_exists( trim( $execFullPath, '"' ) ) || ( file_exists( trim( $execFullPath, '"' ) . '.exe' ) ) ) - $swSVGConvInfo = self::execOutput( $execFullPath . ' -v' ); - $swSVGConvLine = explode("\n",$swSVGConvInfo ,2); - $swSVGConvVer = $swSVGConvLine[0]; - $swSVGConvURL = 'http://librsvg.sourceforge.net/'; - $haveSVGConvVer = true; - } else if ( strstr ($execFullPath, 'inkscape') != false ) { - // Get version info for Inkscape - if ( file_exists( $execBinPath ) ) - $swSVGConvInfo = self::execOutput( $execBinPath . ' -z -V' ); - else if ( file_exists( trim( $execFullPath, '"' ) ) || ( file_exists( trim( $execFullPath, '"' ) . '.exe' ) ) ) - $swSVGConvInfo = self::execOutput( $execFullPath . ' -z -V' ); - $swSVGConvLine = explode("\n",$swSVGConvInfo ,2); - $swSVGConvVer = ltrim( $swSVGConvLine[0], 'Inkscape ' ); - $swSVGConvURL = 'http://www.inkscape.org/'; - $swSVGConvName = ucfirst( $wgSVGConverter ); - $haveSVGConvVer = true; - } - if ( $haveSVGConvVer ) - $software["[$swSVGConvURL $swSVGConvName]"] = $swSVGConvVer; - } - - // Look for TeX support and print the software version info - if ( $wgUseTeX ) { - $binPath = '/usr/bin/'; - $swMathName = Array( - 'ocaml' => 'OCaml', - 'gs' => 'Ghostscript', - 'dvips' => 'Dvips', - 'latex' => 'LaTeX', - 'imagemagick' => 'ImageMagick', - ); - $swMathURL = Array( - 'ocaml' => 'http://caml.inria.fr/', - 'gs' => 'http://www.ghostscript.com/', - 'dvips' => 'http://www.radicaleye.com/dvips.html', - 'latex' => 'http://www.latex-project.org/', - 'imagemagick' => 'http://www.imagemagick.org/', - ); - $swMathExec = Array( - 'ocaml' => 'ocamlc', - 'gs' => 'gs', - 'dvips' => 'dvips', - 'latex' => 'latex', - 'imagemagick' => 'convert', - ); - $swMathParam = Array( - 'ocaml' => '-version', - 'gs' => '-v', - 'dvips' => '-v', - 'latex' => '-v', - 'imagemagick' => '-version', - ); - foreach ( $swMathExec as $swMath => $swMathCmd ) { - $wBinPath = ''; - if ( file_exists( $binPath . 'whereis' ) ) { - $swWhereIsInfo = self::execOutput( $binPath . 'whereis -b ' . $swMathCmd ); - $swWhereIsLine = explode( "\n", $swWhereIsInfo, 2); - $swWhereIsFirstLine = $swWhereIsLine[0]; - $swWhereIsBinPath = explode( ' ', $swWhereIsFirstLine, 3); - if ( count( $swWhereIsBinPath ) > 1 ) - $wBinPath = dirname( $swWhereIsBinPath[1] ); - } else { - $swPathLine = explode( ';', $_SERVER['PATH'] ); - $swPathFound = false; - foreach( $swPathLine as $swPathDir ) { - if ( file_exists( $swPathDir . '/' . $swMathCmd . '.exe' ) && ($swPathFound === false) ) { - $wBinPath = $swPathDir . '/'; - $swPathFound = true; - } - } - } - if ( file_exists( $binPath . $swMathCmd ) || file_exists( $wBinPath . $swMathCmd ) ) { - $swMathInfo = self::execOutput( $swMathCmd . ' ' . $swMathParam[$swMath] ); - $swMathLine = explode( "\n", $swMathInfo, 2); - $swMathVerInfo = $swMathLine[0]; - if ( !strcmp( $swMath, 'gs' ) ) - $swMathVerInfo = str_replace( 'GPL Ghostscript ', '', $swMathVerInfo ); - else if ( !strcmp( $swMath, 'dvips' ) ) { - $swMathVerParts = explode( ' ' , $swMathVerInfo ); - $swMathVerInfo = $swMathVerParts[3]; - } else if ( !strcmp( $swMath, 'imagemagick' ) ) { - list( $head, $tail ) = explode( 'ImageMagick', $swMathVerInfo ); - list( $swMathVerInfo ) = explode('http://www.imagemagick.org', $tail ); - } - $swMathVer[$swMath] = trim( $swMathVerInfo ); - $software["[$swMathURL[$swMath] $swMathName[$swMath]]"] = $swMathVer[$swMath]; - } - } - } - - // Allow a hook to add/remove items + // Allow a hook to add/remove items. wfRunHooks( 'SoftwareInfo', array( &$software ) ); $out = Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMsg( 'version-software' ) ) . @@ -278,138 +130,220 @@ class SpecialVersion extends SpecialPage { " . wfMsg( 'version-software-product' ) . " " . wfMsg( 'version-software-version' ) . " \n"; + foreach( $software as $name => $version ) { $out .= " " . $name . " " . $version . " \n"; - } + } + return $out . Xml::closeElement( 'table' ); } /** - * Return a string of the MediaWiki version with SVN revision if available + * Return a string of the MediaWiki version with SVN revision if available. * * @return mixed */ - public static function getVersion( $flags = '' ) { + public static function getVersion( $flags = '' ) { global $wgVersion, $IP; wfProfileIn( __METHOD__ ); - $svn = self::getSvnRevision( $IP, false, false , false ); - $svnCo = self::getSvnRevision( $IP, true, false , false ); - if ( !$svn ) { + + $info = self::getSvnInfo( $IP ); + if ( !$info ) { $version = $wgVersion; } elseif( $flags === 'nodb' ) { - $version = "$wgVersion (r$svnCo)"; + $version = "$wgVersion (r{$info['checkout-rev']})"; } else { - $version = $wgVersion . wfMsg( 'version-svn-revision', $svn, $svnCo ); + $version = $wgVersion . ' ' . + wfMsg( + 'version-svn-revision', + isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', + $info['checkout-rev'] + ); } + wfProfileOut( __METHOD__ ); return $version; } /** - * Return a string of the MediaWiki version with a link to SVN revision if - * available + * Return a wikitext-formatted string of the MediaWiki version with a link to + * the SVN revision if available. * * @return mixed */ public static function getVersionLinked() { global $wgVersion, $IP; wfProfileIn( __METHOD__ ); - $svn = self::getSvnRevision( $IP, false, false, false ); - $svnCo = self::getSvnRevision( $IP, true, false, false ); - $svnDir = self::getSvnRevision( $IP, true, false, true ); - $viewvcStart = 'http://svn.wikimedia.org/viewvc/mediawiki/'; - $viewvcEnd = '/?pathrev='; - $viewvc = $viewvcStart . $svnDir . $viewvcEnd; - $version = $svn ? $wgVersion . " [{$viewvc}{$svnCo} " . wfMsg( 'version-svn-revision', $svn, $svnCo ) . ']' : $wgVersion; + + $info = self::getSvnInfo( $IP ); + + if ( isset( $info['checkout-rev'] ) ) { + $linkText = wfMsg( + 'version-svn-revision', + isset( $info['directory-rev'] ) ? $info['directory-rev'] : '', + $info['checkout-rev'] + ); + + if ( isset( $info['viewvc-url'] ) ) { + $version = "$wgVersion [{$info['viewvc-url']} $linkText]"; + } else { + $version = "$wgVersion $linkText"; + } + } else { + $version = $wgVersion; + } + wfProfileOut( __METHOD__ ); return $version; } - /** Generate wikitext showing extensions name, URL, author and description */ - function extensionCredits() { + /** + * Returns an array with the base extension types. + * Type is stored as array key, the message as array value. + * + * TODO: ideally this would return all extension types, including + * those added by SpecialVersionExtensionTypes. This is not possible + * since this hook is passing along $this though. + * + * @since 1.17 + * + * @return array + */ + public static function getExtensionTypes() { + if ( self::$extensionTypes === false ) { + self::$extensionTypes = array( + 'specialpage' => wfMsg( 'version-specialpages' ), + 'parserhook' => wfMsg( 'version-parserhooks' ), + 'variable' => wfMsg( 'version-variables' ), + 'media' => wfMsg( 'version-mediahandlers' ), + 'other' => wfMsg( 'version-other' ), + ); + + wfRunHooks( 'ExtensionTypes', array( &self::$extensionTypes ) ); + } + + return self::$extensionTypes; + } + + /** + * Returns the internationalized name for an extension type. + * + * @since 1.17 + * + * @param $type String + * + * @return string + */ + public static function getExtensionTypeName( $type ) { + $types = self::getExtensionTypes(); + return $types[$type]; + } + + /** + * Generate wikitext showing extensions name, URL, author and description. + * + * @return String: Wikitext + */ + function getExtensionCredits() { global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunctions; - if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunctions ) ) + if ( !count( $wgExtensionCredits ) && !count( $wgExtensionFunctions ) && !count( $wgSkinExtensionFunctions ) ) { return ''; + } - $extensionTypes = array( - 'specialpage' => wfMsg( 'version-specialpages' ), - 'parserhook' => wfMsg( 'version-parserhooks' ), - 'variable' => wfMsg( 'version-variables' ), - 'media' => wfMsg( 'version-mediahandlers' ), - 'other' => wfMsg( 'version-other' ), - ); + $extensionTypes = self::getExtensionTypes(); + + /** + * @deprecated as of 1.17, use hook ExtensionTypes instead. + */ wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) ); $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) . Xml::openElement( 'table', array( 'class' => 'wikitable', 'id' => 'sv-ext' ) ); - foreach ( $extensionTypes as $type => $text ) { - if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) { - $out .= $this->openExtType( $text ); - - usort( $wgExtensionCredits[$type], array( $this, 'compare' ) ); - - foreach ( $wgExtensionCredits[$type] as $extension ) { - $version = null; - $subVersion = null; - $subVersionCo = null; - $viewvc = null; - if ( isset( $extension['path'] ) ) { - $subVersion = self::getSvnRevision(dirname($extension['path']), false, true, false); - $subVersionCo = self::getSvnRevision(dirname($extension['path']), true, true, false); - $subVersionDir = self::getSvnRevision(dirname($extension['path']), false, true, true); - if ($subVersionDir) - $viewvc = $subVersionDir . $subVersionCo; - } - if ( isset( $extension['version'] ) ) { - $version = $extension['version']; - } - - $out .= $this->formatCredits( - isset ( $extension['name'] ) ? $extension['name'] : '', - $version, - $subVersion, - $subVersionCo, - $viewvc, - isset ( $extension['author'] ) ? $extension['author'] : '', - isset ( $extension['url'] ) ? $extension['url'] : null, - isset ( $extension['description'] ) ? $extension['description'] : '', - isset ( $extension['descriptionmsg'] ) ? $extension['descriptionmsg'] : null - ); - } + // Make sure the 'other' type is set to an array. + if ( !array_key_exists( 'other', $wgExtensionCredits ) ) { + $wgExtensionCredits['other'] = array(); + } + + // Find all extensions that do not have a valid type and give them the type 'other'. + foreach ( $wgExtensionCredits as $type => $extensions ) { + if ( !array_key_exists( $type, $extensionTypes ) ) { + $wgExtensionCredits['other'] = array_merge( $wgExtensionCredits['other'], $extensions ); } } + + // Loop through the extension categories to display their extensions in the list. + foreach ( $extensionTypes as $type => $message ) { + if ( $type != 'other' ) { + $out .= $this->getExtensionCategory( $type, $message ); + } + } + + // We want the 'other' type to be last in the list. + $out .= $this->getExtensionCategory( 'other', $extensionTypes['other'] ); if ( count( $wgExtensionFunctions ) ) { - $out .= $this->openExtType( wfMsg( 'version-extension-functions' ) ); + $out .= $this->openExtType( wfMsg( 'version-extension-functions' ), 'extension-functions' ); $out .= '' . $this->listToText( $wgExtensionFunctions ) . "\n"; } if ( $cnt = count( $tags = $wgParser->getTags() ) ) { for ( $i = 0; $i < $cnt; ++$i ) $tags[$i] = "<{$tags[$i]}>"; - $out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ) ); + $out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ), 'parser-tags' ); $out .= '' . $this->listToText( $tags ). "\n"; } if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) { - $out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ) ); + $out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ), 'parser-function-hooks' ); $out .= '' . $this->listToText( $fhooks ) . "\n"; } if ( count( $wgSkinExtensionFunctions ) ) { - $out .= $this->openExtType( wfMsg( 'version-skin-extension-functions' ) ); + $out .= $this->openExtType( wfMsg( 'version-skin-extension-functions' ), 'skin-extension-functions' ); $out .= '' . $this->listToText( $wgSkinExtensionFunctions ) . "\n"; } + $out .= Xml::closeElement( 'table' ); + return $out; } + + /** + * Creates and returns the HTML for a single extension category. + * + * @since 1.17 + * + * @param $type String + * @param $message String + * + * @return string + */ + protected function getExtensionCategory( $type, $message ) { + global $wgExtensionCredits; + + $out = ''; + + if ( array_key_exists( $type, $wgExtensionCredits ) && count( $wgExtensionCredits[$type] ) > 0 ) { + $out .= $this->openExtType( $message, 'credits-' . $type ); + + usort( $wgExtensionCredits[$type], array( $this, 'compare' ) ); + + foreach ( $wgExtensionCredits[$type] as $extension ) { + $out .= $this->getCreditsForExtension( $extension ); + } + } + + return $out; + } - /** Callback to sort extensions by type */ + /** + * Callback to sort extensions by type. + */ function compare( $a, $b ) { global $wgLang; if( $a['name'] === $b['name'] ) { @@ -421,40 +355,93 @@ class SpecialVersion extends SpecialPage { } } - function formatCredits( $name, $version = null, $subVersion = null, $subVersionCo = null, $subVersionURL = null, $author = null, $url = null, $description = null, $descriptionMsg = null ) { - $haveSubversion = $subVersion; - $extension = isset( $url ) ? "[$url $name]" : $name; - $version = isset( $version ) ? wfMsg( 'version-version', $version ) : ''; - $subVersion = isset( $subVersion ) ? wfMsg( 'version-svn-revision', $subVersion, $subVersionCo ) : ''; - $subVersion = isset( $subVersionURL ) ? "[$subVersionURL $subVersion]" : $subVersion; - - # Look for a localized description - if( isset( $descriptionMsg ) ) { - $msg = wfMsg( $descriptionMsg ); - if ( !wfEmptyMsg( $descriptionMsg, $msg ) && $msg != '' ) { - $description = $msg; + /** + * Creates and formats the creidts for a single extension and returns this. + * + * @param $extension Array + * + * @return string + */ + function getCreditsForExtension( array $extension ) { + $name = isset( $extension['name'] ) ? $extension['name'] : '[no name]'; + + if ( isset( $extension['path'] ) ) { + $svnInfo = self::getSvnInfo( dirname($extension['path']) ); + $directoryRev = isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : null; + $checkoutRev = isset( $svnInfo['checkout-rev'] ) ? $svnInfo['checkout-rev'] : null; + $viewvcUrl = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : null; + } else { + $directoryRev = null; + $checkoutRev = null; + $viewvcUrl = null; + } + + # Make main link (or just the name if there is no URL). + if ( isset( $extension['url'] ) ) { + $mainLink = "[{$extension['url']} $name]"; + } else { + $mainLink = $name; + } + + if ( isset( $extension['version'] ) ) { + $versionText = '' . + wfMsg( 'version-version', $extension['version'] ) . + ''; + } else { + $versionText = ''; + } + + # Make subversion text/link. + if ( $checkoutRev ) { + $svnText = wfMsg( 'version-svn-revision', $directoryRev, $checkoutRev ); + $svnText = isset( $viewvcUrl ) ? "[$viewvcUrl $svnText]" : $svnText; + } else { + $svnText = false; + } + + # Make description text. + $description = isset ( $extension['description'] ) ? $extension['description'] : ''; + + if( isset ( $extension['descriptionmsg'] ) ) { + # Look for a localized description. + $descriptionMsg = $extension['descriptionmsg']; + + if( is_array( $descriptionMsg ) ) { + $descriptionMsgKey = $descriptionMsg[0]; // Get the message key + array_shift( $descriptionMsg ); // Shift out the message key to get the parameters only + array_map( "htmlspecialchars", $descriptionMsg ); // For sanity + $msg = wfMsg( $descriptionMsgKey, $descriptionMsg ); + } else { + $msg = wfMsg( $descriptionMsg ); } + if ( !wfEmptyMsg( $descriptionMsg, $msg ) && $msg != '' ) { + $description = $msg; + } } - if ( $haveSubversion ) { - $extNameVer = " - $extension $version - $subVersion"; + if ( $svnText !== false ) { + $extNameVer = " + $mainLink $versionText + $svnText"; } else { - $extNameVer = " - $extension $version"; + $extNameVer = " + $mainLink $versionText"; } + + $author = isset ( $extension['author'] ) ? $extension['author'] : array(); $extDescAuthor = "$description - " . $this->listToText( (array)$author ) . " - \n"; - return $ret = $extNameVer . $extDescAuthor; - return $ret; + " . $this->listToText( (array)$author, false ) . " + \n"; + + return $extNameVer . $extDescAuthor; } /** - * @return string + * Generate wikitext showing hooks in $wgHooks. + * + * @return String: wikitext */ - function wgHooks() { + private function getWgHooks() { global $wgHooks; if ( count( $wgHooks ) ) { @@ -480,36 +467,45 @@ class SpecialVersion extends SpecialPage { return ''; } - private function openExtType($text, $name = null) { + private function openExtType( $text, $name = null ) { $opt = array( 'colspan' => 4 ); $out = ''; - if(!$this->firstExtOpened) { + if( $this->firstExtOpened ) { // Insert a spacing line - $out .= '' . Xml::element( 'td', $opt ) . "\n"; + $out .= '' . Html::element( 'td', $opt ) . "\n"; + } + $this->firstExtOpened = true; + + if( $name ) { + $opt['id'] = "sv-$name"; } - $this->firstExtOpened = false; - - if($name) { $opt['id'] = "sv-$name"; } - $out .= "" . Xml::element( 'th', $opt, $text) . "\n"; + $out .= "" . Xml::element( 'th', $opt, $text ) . "\n"; + return $out; } /** - * @return string + * Get information about client's IP address. + * + * @return String: HTML fragment */ - function IPInfo() { + private function IPInfo() { $ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) ); return "\n" . "visited from $ip"; } /** - * @param array $list - * @return string + * Convert an array of items into a list for display. + * + * @param $list Array of elements to display + * @param $sort Boolean: whether to sort the items in $list + * + * @return String */ - function listToText( $list ) { + function listToText( $list, $sort = true ) { $cnt = count( $list ); if ( $cnt == 1 ) { @@ -519,15 +515,20 @@ class SpecialVersion extends SpecialPage { return ''; } else { global $wgLang; - sort( $list ); + if ( $sort ) { + sort( $list ); + } return $wgLang->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) ); } } /** - * @param mixed $list Will convert an array to string if given and return - * the paramater unaltered otherwise - * @return mixed + * Convert an array or object to a string for display. + * + * @param $list Mixed: will convert an array to string if given and return + * the paramater unaltered otherwise + * + * @return Mixed */ static function arrayToString( $list ) { if( is_array( $list ) && count( $list ) == 1 ) @@ -547,18 +548,20 @@ class SpecialVersion extends SpecialPage { } /** - * Retrieve the revision number of a Subversion working directory. + * Get an associative array of information about a given path, from its .svn + * subdirectory. Returns false on error, such as if the directory was not + * checked out with subversion. * - * @param String $dir Directory of the svn checkout - * @param Boolean $coRev optional to return value whether is Last Modified - * or Checkout revision number - * @param Boolean $extension optional to check the path whether is from - * Wikimedia SVN server or not - * @param Boolean $relPath optional to get the end part of the checkout path - * @return mixed revision number as int, end part of the checkout path, - * or false if not a SVN checkout + * Returned keys are: + * Required: + * checkout-rev The revision which was checked out + * Optional: + * directory-rev The revision when the directory was last modified + * url The subversion URL of the directory + * repo-url The base URL of the repository + * viewvc-url A ViewVC URL pointing to the checked-out revision */ - public static function getSvnRevision( $dir, $coRev = false, $extension = false, $relPath = false) { + public static function getSvnInfo( $dir ) { // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html $entries = $dir . '/.svn/entries'; @@ -566,10 +569,13 @@ class SpecialVersion extends SpecialPage { return false; } - $content = file( $entries ); + $lines = file( $entries ); + if ( !count( $lines ) ) { + return false; + } // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4) - if( preg_match( '/^<\?xml/', $content[0] ) ) { + if( preg_match( '/^<\?xml/', $lines[0] ) ) { // subversion is release <= 1.3 if( !function_exists( 'simplexml_load_file' ) ) { // We could fall back to expat... YUCK @@ -586,51 +592,60 @@ class SpecialVersion extends SpecialPage { if( $xml->entry[0]['name'] == '' ) { // The directory entry should always have a revision marker. if( $entry['revision'] ) { - return intval( $entry['revision'] ); + return array( 'checkout-rev' => intval( $entry['revision'] ) ); } } } } + + return false; + } + + // Subversion is release 1.4 or above. + if ( count( $lines ) < 11 ) { return false; + } + + $info = array( + 'checkout-rev' => intval( trim( $lines[3] ) ), + 'url' => trim( $lines[4] ), + 'repo-url' => trim( $lines[5] ), + 'directory-rev' => intval( trim( $lines[10] ) ) + ); + + if ( isset( self::$viewvcUrls[$info['repo-url']] ) ) { + $viewvc = str_replace( + $info['repo-url'], + self::$viewvcUrls[$info['repo-url']], + $info['url'] + ); + + $pathRelativeToRepo = substr( $info['url'], strlen( $info['repo-url'] ) ); + $viewvc .= '/?pathrev='; + $viewvc .= urlencode( $info['checkout-rev'] ); + $info['viewvc-url'] = $viewvc; + } + + return $info; + } + + /** + * Retrieve the revision number of a Subversion working directory. + * + * @param $dir String: directory of the svn checkout + * + * @return Integer: revision number as int + */ + public static function getSvnRevision( $dir ) { + $info = self::getSvnInfo( $dir ); + + if ( $info === false ) { + return false; + } elseif ( isset( $info['checkout-rev'] ) ) { + return $info['checkout-rev']; } else { - // subversion is release 1.4 or above - if ($relPath) { - $endPath = strstr( $content[4], 'tags' ); - if (!$endPath) { - $endPath = strstr( $content[4], 'branches' ); - if (!$endPath) { - $endPath = strstr( $content[4], 'trunk' ); - if (!$endPath) - return false; - } - } - $endPath = trim ( $endPath ); - if ($extension) { - $wmSvnPath = 'svn.wikimedia.org/svnroot/mediawiki'; - $isWMSvn = strstr($content[5],$wmSvnPath); - if (!strcmp($isWMSvn,null)) { - return false; - } else { - $viewvcStart = 'http://svn.wikimedia.org/viewvc/mediawiki/'; - if (strstr( $content[4], 'trunk' )) - $viewvcEnd = '/?pathrev='; - else - // Avoids 404 error using pathrev when it does not found - $viewvcEnd = '/?revision='; - $viewvc = $viewvcStart . $endPath . $viewvcEnd; - return $viewvc; - } - } - return $endPath; - } - if ($coRev) - // get the directory checkout revsion number - return intval( $content[3]) ; - else - // get the directory last modified revision number - return intval( $content[10] ); + return false; } } - /**#@-*/ }