fc7fc52c069ce28d3a0ebbb98bce5c0213908beb
3 * Give information about the version of MediaWiki, PHP, the DB and extensions
6 * @subpackage SpecialPage
10 * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
11 * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
12 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
18 function wfSpecialVersion() {
19 $version = new SpecialVersion
;
23 class SpecialVersion
{
24 private $firstExtOpened = true;
32 $wgOut->addHTML( '<div dir="ltr">' );
34 $this->MediaWikiCredits() .
35 $this->extensionCredits() .
38 $wgOut->addHTML( $this->IPInfo() );
39 $wgOut->addHTML( '</div>' );
47 * Return wiki text showing the licence information and third party
48 * software versions (apache, php, mysql).
51 function MediaWikiCredits() {
52 $version = self
::getVersion();
53 $dbr =& wfGetDB( DB_SLAVE
);
57 This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
58 copyright (C) 2001-2007 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
59 Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason,
60 Niklas Laxström, Domas Mituzas, Rob Church and others.
62 MediaWiki is free software; you can redistribute it and/or modify
63 it under the terms of the GNU General Public License as published by
64 the Free Software Foundation; either version 2 of the License, or
65 (at your option) any later version.
67 MediaWiki is distributed in the hope that it will be useful,
68 but WITHOUT ANY WARRANTY; without even the implied warranty of
69 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70 GNU General Public License for more details.
72 You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
73 along with this program; if not, write to the Free Software
74 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
75 or [http://www.gnu.org/copyleft/gpl.html read it online]
77 * [http://www.mediawiki.org/ MediaWiki]: $version
78 * [http://www.php.net/ PHP]: " . phpversion() . " (" . php_sapi_name() . ")
79 * " . $dbr->getSoftwareLink() . ": " . $dbr->getServerVersion();
81 return str_replace( "\t\t", '', $ret ) . "\n";
84 /** Return a string of the MediaWiki version with SVN revision if available */
85 public static function getVersion() {
86 global $wgVersion, $IP;
87 $svn = self
::getSvnRevision( $IP );
88 return $svn ?
"$wgVersion (r$svn)" : $wgVersion;
91 /** Generate wikitext showing extensions name, URL, author and description */
92 function extensionCredits() {
93 global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunction;
95 if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunction ) )
98 $extensionTypes = array(
99 'specialpage' => 'Special pages',
100 'parserhook' => 'Parser hooks',
101 'variable' => 'Variables',
104 wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
106 $out = "<h2>Extensions</h2>\n";
107 $out .= wfOpenElement('table', array('id' => 'sv-ext') );
109 foreach ( $extensionTypes as $type => $text ) {
110 if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) {
111 $out .= $this->openExtType( $text );
113 usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
115 foreach ( $wgExtensionCredits[$type] as $extension ) {
116 $out .= $this->formatCredits(
117 isset ( $extension['name'] ) ?
$extension['name'] : '',
118 isset ( $extension['version'] ) ?
$extension['version'] : null,
119 isset ( $extension['author'] ) ?
$extension['author'] : '',
120 isset ( $extension['url'] ) ?
$extension['url'] : null,
121 isset ( $extension['description'] ) ?
$extension['description'] : ''
127 if ( count( $wgExtensionFunctions ) ) {
128 $out .= $this->openExtType('Extension functions');
129 $out .= '<tr><td colspan="3">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n";
132 if ( $cnt = count( $tags = $wgParser->getTags() ) ) {
133 for ( $i = 0; $i < $cnt; ++
$i )
134 $tags[$i] = "<{$tags[$i]}>";
135 $out .= $this->openExtType('Parser extension tags');
136 $out .= '<tr><td colspan="3">' . $this->listToText( $tags ). "</td></tr>\n";
139 if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) {
140 $out .= $this->openExtType('Parser function hooks');
141 $out .= '<tr><td colspan="3">' . $this->listToText( $fhooks ) . "</td></tr>\n";
144 if ( count( $wgSkinExtensionFunction ) ) {
145 $out .= $this->openExtType('Skin extension functions');
146 $out .= '<tr><td colspan="3">' . $this->listToText( $wgSkinExtensionFunction ) . "</td></tr>\n";
148 $out .= wfCloseElement( 'table' );
152 /** Callback to sort extensions by type */
153 function compare( $a, $b ) {
154 if ( $a['name'] === $b['name'] )
157 return Language
::lc( $a['name'] ) > Language
::lc( $b['name'] ) ?
1 : -1;
160 function formatCredits( $name, $version = null, $author = null, $url = null, $description = null) {
165 if ( isset( $version ) )
166 $ret .= " (version $version)";
171 $ret .= "<td>$description</td>";
172 $ret .= "<td>" . $this->listToText( (array)$author ) . "</td>";
183 if ( count( $wgHooks ) ) {
184 $myWgHooks = $wgHooks;
187 $ret = "<h2>Hooks</h2>\n"
188 . wfOpenElement('table', array('id' => 'sv-hooks') )
189 . "<tr><th>Hook name</th><th>Subscribed by</th></tr>\n";
191 foreach ($myWgHooks as $hook => $hooks)
192 $ret .= "<tr><td>$hook</td><td>" . $this->listToText( $hooks ) . "</td></tr>\n";
200 private function openExtType($text, $name = null) {
201 $opt = array( 'colspan' => 3 );
204 if(!$this->firstExtOpened
) {
205 // Insert a spacing line
206 $out .= '<tr class="sv-space">' . wfElement( 'td', $opt ) . "</tr>\n";
208 $this->firstExtOpened
= false;
210 if($name) { $opt['id'] = "sv-$name"; }
212 $out .= "<tr>" . wfElement( 'th', $opt, $text) . "</tr>\n";
222 $ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
223 return "<!-- visited from $ip -->\n" .
224 "<span style='display:none'>visited from $ip</span>";
231 function listToText( $list ) {
232 $cnt = count( $list );
235 // Enforce always returning a string
236 return (string)$this->arrayToString( $list[0] );
237 } elseif ( $cnt == 0 ) {
240 $t = array_slice( $list, 0, $cnt - 1 );
241 $one = array_map( array( &$this, 'arrayToString' ), $t );
242 $two = $this->arrayToString( $list[$cnt - 1] );
244 return implode( ', ', $one ) . " and $two";
251 * @param mixed $list Will convert an array to string if given and return
252 * the paramater unaltered otherwise
255 function arrayToString( $list ) {
256 if ( ! is_array( $list ) ) {
259 $class = get_class( $list[0] );
260 return "($class, {$list[1]})";
265 * Retrieve the revision number of a Subversion working directory.
270 * @return mixed revision number as int, or false if not a SVN checkout
272 public static function getSvnRevision( $dir ) {
273 // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
274 $entries = $dir . '/.svn/entries';
276 if( !file_exists( $entries ) ) {
280 $content = file( $entries );
282 // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
283 if( preg_match( '/^<\?xml/', $content[0] ) ) {
284 // subversion is release <= 1.3
285 if( !function_exists( 'simplexml_load_file' ) ) {
286 // We could fall back to expat... YUCK
290 $xml = simplexml_load_file( $entries, "SimpleXMLElement", LIBXML_NOWARNING
);
293 foreach( $xml->entry
as $entry ) {
294 if( $xml->entry
[0]['name'] == '' ) {
295 // The directory entry should always have a revision marker.
296 if( $entry['revision'] ) {
297 return intval( $entry['revision'] );
304 // subversion is release 1.4
305 return intval( $content[3] );