3 * Give information about the version of MediaWiki, PHP, the DB and extensions
5 * @addtogroup SpecialPage
7 * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
8 * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
9 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
15 function wfSpecialVersion() {
16 $version = new SpecialVersion
;
20 class SpecialVersion
{
21 private $firstExtOpened = true;
30 $this->MediaWikiCredits() .
31 $this->systemInformation() .
32 $this->extensionCredits() .
35 $wgOut->addHTML( $this->IPInfo() );
43 * Return wiki text showing the licence information and third party
44 * software versions (apache, php, mysql).
47 function MediaWikiCredits() {
48 $ret = "<h2>" . wfMsgExt( 'version-licence', array( 'parseinline' ) ) . "</h2>\n";
53 This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
54 copyright (C) 2001-2007 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
55 Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason,
56 Niklas Laxström, Domas Mituzas, Rob Church and others.
58 MediaWiki is free software; you can redistribute it and/or modify
59 it under the terms of the GNU General Public License as published by
60 the Free Software Foundation; either version 2 of the License, or
61 (at your option) any later version.
63 MediaWiki is distributed in the hope that it will be useful,
64 but WITHOUT ANY WARRANTY; without even the implied warranty of
65 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 GNU General Public License for more details.
68 You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
69 along with this program; if not, write to the Free Software
70 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
71 or [http://www.gnu.org/copyleft/gpl.html read it online]
74 $translation = wfMsgExt( 'version-licence-text', array( 'parseline' ) );
75 if( !( wfEmptyMsg( 'version-licence-text', $translation ) ||
$translation == '-' ||
$translation == '' ) ) {
76 $ret .= "<h3>" . wfMsgExt( 'version-licence-header', array( 'parseinline' ) ) . "</h3>\n";
79 return str_replace( "\t\t", '', $ret ) . "\n";
82 /** Return a string of the MediaWiki version with SVN revision if available */
83 public static function getVersion() {
84 global $wgVersion, $IP;
85 $svn = self
::getSvnRevision( $IP );
86 return $svn ?
"$wgVersion (r$svn)" : $wgVersion;
89 /** Generate wikitext showing extensions name, URL, author and description */
90 function extensionCredits() {
91 global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunction;
93 if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunction ) )
96 $extensionTypes = array(
97 'specialpage' => wfMsgExt( 'version-specialpages', array( 'parseinline' ) ),
98 'parserhook' => wfMsgExt( 'version-parserhooks', array( 'parseinline' ) ),
99 'variable' => wfMsgExt( 'version-variables', array( 'parseinline' ) ),
100 'other' => wfMsgExt( 'version-other', array( 'parseinline' ) ),
102 wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
104 $out = "<h2>" . wfMsgExt( 'version-extensions', array( 'parseinline' ) ) . "</h2>\n";
105 $out .= Xml
::openElement( 'table', array('id' => 'sv-ext', 'dir' => 'ltr' ) );
107 foreach ( $extensionTypes as $type => $text ) {
108 if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) {
109 $out .= $this->openExtType( $text );
111 usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
113 foreach ( $wgExtensionCredits[$type] as $extension ) {
114 $out .= $this->formatCredits(
115 isset ( $extension['name'] ) ?
$extension['name'] : '',
116 isset ( $extension['version'] ) ?
$extension['version'] : null,
117 isset ( $extension['author'] ) ?
$extension['author'] : '',
118 isset ( $extension['url'] ) ?
$extension['url'] : null,
119 isset ( $extension['description'] ) ?
$extension['description'] : ''
125 if ( count( $wgExtensionFunctions ) ) {
126 $out .= $this->openExtType( wfMsgExt( 'version-extension-functions', array( 'parseinline' ) ) );
127 $out .= '<tr><td colspan="3">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n";
130 if ( $cnt = count( $tags = $wgParser->getTags() ) ) {
131 for ( $i = 0; $i < $cnt; ++
$i )
132 $tags[$i] = "<{$tags[$i]}>";
133 $out .= $this->openExtType( wfMsgExt( 'version-parser-extensiontags', array( 'parseinline' ) ) );
134 $out .= '<tr><td colspan="3">' . $this->listToText( $tags ). "</td></tr>\n";
137 if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) {
138 $out .= $this->openExtType( wfMsgExt( 'version-parser-function-hooks', array( 'parseinline' ) ) );
139 $out .= '<tr><td colspan="3">' . $this->listToText( $fhooks ) . "</td></tr>\n";
142 if ( count( $wgSkinExtensionFunction ) ) {
143 $out .= $this->openExtType( wfMsgExt( 'version-skin-extension-functions', array( 'parseinline' ) ) );
144 $out .= '<tr><td colspan="3">' . $this->listToText( $wgSkinExtensionFunction ) . "</td></tr>\n";
146 $out .= Xml
::closeElement( 'table' );
150 /** Callback to sort extensions by type */
151 function compare( $a, $b ) {
152 if ( $a['name'] === $b['name'] )
155 return Language
::lc( $a['name'] ) > Language
::lc( $b['name'] ) ?
1 : -1;
158 function formatCredits( $name, $version = null, $author = null, $url = null, $description = null) {
163 if ( isset( $version ) )
164 $ret .= " (version $version)";
169 $ret .= "<td>$description</td>";
170 $ret .= "<td>" . $this->listToText( (array)$author ) . "</td>";
181 if ( count( $wgHooks ) ) {
182 $myWgHooks = $wgHooks;
185 $ret = "<h2>" . wfMsgExt( 'version-hooks', array( 'parseinline' ) ) . "</h2>\n";
186 $ret .= Xml
::openElement( 'table', array( 'id' => 'sv-hooks', 'dir' => 'ltr' ) );
188 <th>" . wfMsgExt( 'version-hook-name', array( 'parseinline' ) ) . "</th>
189 <th>" . wfMsgExt( 'version-hook-subscribedby', array( 'parseinline' ) ) . "</th>
192 foreach ($myWgHooks as $hook => $hooks)
195 <td>" . $this->listToText( $hooks ) . "</td>
198 $ret .= Xml
::closeElement( 'table' );
204 function systemInformation() {
205 $version = self
::getVersion();
206 $dbr = wfGetDB( DB_SLAVE
);
208 $ret = "<h2>" . wfMsgExt( 'version-system', array( 'parseinline' ) ) . "</h2>\n";
209 $ret .= Xml
::openElement( 'table', array( 'id' => 'sv-software', 'dir' => 'ltr' ) );
211 <th>" . wfMsgExt( 'version-software', array( 'parseinline' ) ) . "</th>
212 <th>" . wfMsgExt( 'version-version', array( 'parseinline' ) ) . "</th>
215 <td>[http://www.mediawiki.org/ MediaWiki]:</td>
219 <td>[http://www.php.net/ PHP]:</td>
220 <td>" . phpversion() . " (" . php_sapi_name() . ")</td>
223 <td>" . $dbr->getSoftwareLink() . ":</td>
224 <td>" . $dbr->getServerVersion() . "</td>
226 $ret .= Xml
::closeElement( 'table' );
231 private function openExtType($text, $name = null) {
232 $opt = array( 'colspan' => 3 );
235 if(!$this->firstExtOpened
) {
236 // Insert a spacing line
237 $out .= '<tr class="sv-space">' . Xml
::tags( 'td', $opt, '' ) . "</tr>\n";
239 $this->firstExtOpened
= false;
241 if($name) { $opt['id'] = "sv-$name"; }
243 $out .= "<tr>" . Xml
::tags( 'th', $opt, $text) . "</tr>\n";
253 $ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
254 return "<!-- visited from $ip -->\n" .
255 "<span style='display:none'>visited from $ip</span>";
262 function listToText( $list ) {
264 if ( count( $list ) ) {
266 return implode( ', ', $list );
273 * Retrieve the revision number of a Subversion working directory.
276 * @return mixed revision number as int, or false if not a SVN checkout
278 public static function getSvnRevision( $dir ) {
279 // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
280 $entries = $dir . '/.svn/entries';
282 if( !file_exists( $entries ) ) {
286 $content = file( $entries );
288 // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
289 if( preg_match( '/^<\?xml/', $content[0] ) ) {
290 // subversion is release <= 1.3
291 if( !function_exists( 'simplexml_load_file' ) ) {
292 // We could fall back to expat... YUCK
296 // SimpleXml whines about the xmlns...
297 wfSuppressWarnings();
298 $xml = simplexml_load_file( $entries );
302 foreach( $xml->entry
as $entry ) {
303 if( $xml->entry
[0]['name'] == '' ) {
304 // The directory entry should always have a revision marker.
305 if( $entry['revision'] ) {
306 return intval( $entry['revision'] );
313 // subversion is release 1.4
314 return intval( $content[3] );