]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/specials/SpecialVersion.php
Mediawiki 1.15.2
[autoinstalls/mediawiki.git] / includes / specials / SpecialVersion.php
1 <?php
2
3 /**
4  * Give information about the version of MediaWiki, PHP, the DB and extensions
5  *
6  * @ingroup SpecialPage
7  *
8  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
9  * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
10  * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
11  */
12 class SpecialVersion extends SpecialPage {
13         private $firstExtOpened = true;
14
15         function __construct(){
16                 parent::__construct( 'Version' );       
17         }
18
19         /**
20          * main()
21          */
22         function execute( $par ) {
23                 global $wgOut, $wgMessageCache, $wgSpecialVersionShowHooks;
24                 $wgMessageCache->loadAllMessages();
25
26                 $this->setHeaders();
27                 $this->outputHeader();
28
29                 $wgOut->addHTML( '<div dir="ltr">' );
30                 $text = 
31                         $this->MediaWikiCredits() .
32                         $this->softwareInformation() .
33                         $this->extensionCredits();
34                 if ( $wgSpecialVersionShowHooks ) {
35                         $text .= $this->wgHooks();
36                 }
37                 $wgOut->addWikiText( $text );
38                 $wgOut->addHTML( $this->IPInfo() );
39                 $wgOut->addHTML( '</div>' );
40         }
41
42         /**#@+
43          * @private
44          */
45
46         /**
47          * @return wiki text showing the license information
48          */
49         static function MediaWikiCredits() {
50                 $ret = Xml::element( 'h2', array( 'id' => 'mw-version-license' ), wfMsg( 'version-license' ) ) .
51                 "__NOTOC__
52                 This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
53                 copyright (C) 2001-2009 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
54                 Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason,
55                 Niklas Laxström, Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor,
56                 Aaron Schulz and others.
57
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.
62
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.
67
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/licenses/old-licenses/gpl-2.0.html read it online].
72                 ";
73
74                 return str_replace( "\t\t", '', $ret ) . "\n";
75         }
76
77         /**
78          * @return wiki text showing the third party software versions (apache, php, mysql).
79          */
80         static function softwareInformation() {
81                 $dbr = wfGetDB( DB_SLAVE );
82
83                 return Xml::element( 'h2', array( 'id' => 'mw-version-software' ), wfMsg( 'version-software' ) ) .
84                         Xml::openElement( 'table', array( 'id' => 'sv-software' ) ) .
85                                 "<tr>
86                                         <th>" . wfMsg( 'version-software-product' ) . "</th>
87                                         <th>" . wfMsg( 'version-software-version' ) . "</th>
88                                 </tr>\n
89                                 <tr>
90                                         <td>[http://www.mediawiki.org/ MediaWiki]</td>
91                                         <td>" . self::getVersionLinked() . "</td>
92                                 </tr>\n
93                                 <tr>
94                                         <td>[http://www.php.net/ PHP]</td>
95                                         <td>" . phpversion() . " (" . php_sapi_name() . ")</td>
96                                 </tr>\n
97                                 <tr>
98                                         <td>" . $dbr->getSoftwareLink() . "</td>
99                                         <td>" . $dbr->getServerVersion() . "</td>
100                                 </tr>\n" .
101                         Xml::closeElement( 'table' );
102         }
103
104         /**
105          * Return a string of the MediaWiki version with SVN revision if available
106          *
107          * @return mixed
108          */
109         public static function getVersion() {
110                 global $wgVersion, $IP;
111                 wfProfileIn( __METHOD__ );
112                 $svn = self::getSvnRevision( $IP );
113                 $version = $svn ? "$wgVersion (r$svn)" : $wgVersion;
114                 wfProfileOut( __METHOD__ );
115                 return $version;
116         }
117         
118         /**
119          * Return a string of the MediaWiki version with a link to SVN revision if
120          * available
121          *
122          * @return mixed
123          */
124         public static function getVersionLinked() {
125                 global $wgVersion, $IP;
126                 wfProfileIn( __METHOD__ );
127                 $svn = self::getSvnRevision( $IP );
128                 $viewvc = 'http://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/?pathrev=';
129                 $version = $svn ? "$wgVersion ([{$viewvc}{$svn} r$svn])" : $wgVersion;
130                 wfProfileOut( __METHOD__ );
131                 return $version;
132         }
133
134         /** Generate wikitext showing extensions name, URL, author and description */
135         function extensionCredits() {
136                 global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunctions;
137
138                 if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunctions ) )
139                         return '';
140
141                 $extensionTypes = array(
142                         'specialpage' => wfMsg( 'version-specialpages' ),
143                         'parserhook' => wfMsg( 'version-parserhooks' ),
144                         'variable' => wfMsg( 'version-variables' ),
145                         'media' => wfMsg( 'version-mediahandlers' ),
146                         'other' => wfMsg( 'version-other' ),
147                 );
148                 wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
149
150                 $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) .
151                         Xml::openElement( 'table', array( 'id' => 'sv-ext' ) );
152
153                 foreach ( $extensionTypes as $type => $text ) {
154                         if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) {
155                                 $out .= $this->openExtType( $text );
156
157                                 usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
158
159                                 foreach ( $wgExtensionCredits[$type] as $extension ) {
160                                         $version = null;
161                                         $subVersion = '';
162                                         if ( isset( $extension['version'] ) ) {
163                                                 $version = $extension['version'];
164                                         }
165                                         if ( isset( $extension['svn-revision'] ) && 
166                                                 preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/', 
167                                                         $extension['svn-revision'], $m ) ) {
168                                                 $subVersion = 'r' . $m[1];
169                                         }
170
171                                         if( $version && $subVersion ) {
172                                                 $version = $version . ' [' . $subVersion . ']';
173                                         } elseif ( !$version && $subVersion ) {
174                                                 $version = $subVersion;
175                                         }
176
177                                         $out .= $this->formatCredits(
178                                                 isset ( $extension['name'] )           ? $extension['name']        : '',
179                                                 $version,
180                                                 isset ( $extension['author'] )         ? $extension['author']      : '',
181                                                 isset ( $extension['url'] )            ? $extension['url']         : null,
182                                                 isset ( $extension['description'] )    ? $extension['description'] : '',
183                                                 isset ( $extension['descriptionmsg'] ) ? $extension['descriptionmsg'] : ''
184                                         );
185                                 }
186                         }
187                 }
188
189                 if ( count( $wgExtensionFunctions ) ) {
190                         $out .= $this->openExtType( wfMsg( 'version-extension-functions' ) );
191                         $out .= '<tr><td colspan="3">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n";
192                 }
193
194                 if ( $cnt = count( $tags = $wgParser->getTags() ) ) {
195                         for ( $i = 0; $i < $cnt; ++$i )
196                                 $tags[$i] = "&lt;{$tags[$i]}&gt;";
197                         $out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ) );
198                         $out .= '<tr><td colspan="3">' . $this->listToText( $tags ). "</td></tr>\n";
199                 }
200
201                 if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) {
202                         $out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ) );
203                         $out .= '<tr><td colspan="3">' . $this->listToText( $fhooks ) . "</td></tr>\n";
204                 }
205
206                 if ( count( $wgSkinExtensionFunctions ) ) {
207                         $out .= $this->openExtType( wfMsg( 'version-skin-extension-functions' ) );
208                         $out .= '<tr><td colspan="3">' . $this->listToText( $wgSkinExtensionFunctions ) . "</td></tr>\n";
209                 }
210                 $out .= Xml::closeElement( 'table' );
211                 return $out;
212         }
213
214         /** Callback to sort extensions by type */
215         function compare( $a, $b ) {
216                 global $wgLang;
217                 if( $a['name'] === $b['name'] ) {
218                         return 0;
219                 } else {
220                         return $wgLang->lc( $a['name'] ) > $wgLang->lc( $b['name'] )
221                                 ? 1
222                                 : -1;
223                 }
224         }
225
226         function formatCredits( $name, $version = null, $author = null, $url = null, $description = null, $descriptionMsg = null ) {
227                 $extension = isset( $url ) ? "[$url $name]" : $name;
228                 $version = isset( $version ) ? "(" . wfMsg( 'version-version' ) . " $version)" : '';
229
230                 # Look for a localized description
231                 if( isset( $descriptionMsg ) ) {
232                         $msg = wfMsg( $descriptionMsg );
233                         if ( !wfEmptyMsg( $descriptionMsg, $msg ) && $msg != '' ) {
234                                 $description = $msg;
235                         }
236                 }
237
238                 return "<tr>
239                                 <td><em>$extension $version</em></td>
240                                 <td>$description</td>
241                                 <td>" . $this->listToText( (array)$author ) . "</td>
242                         </tr>\n";
243         }
244
245         /**
246          * @return string
247          */
248         function wgHooks() {
249                 global $wgHooks;
250
251                 if ( count( $wgHooks ) ) {
252                         $myWgHooks = $wgHooks;
253                         ksort( $myWgHooks );
254
255                         $ret = Xml::element( 'h2', array( 'id' => 'mw-version-hooks' ), wfMsg( 'version-hooks' ) ) .
256                                 Xml::openElement( 'table', array( 'id' => 'sv-hooks' ) ) .
257                                 "<tr>
258                                         <th>" . wfMsg( 'version-hook-name' ) . "</th>
259                                         <th>" . wfMsg( 'version-hook-subscribedby' ) . "</th>
260                                 </tr>\n";
261
262                         foreach ( $myWgHooks as $hook => $hooks )
263                                 $ret .= "<tr>
264                                                 <td>$hook</td>
265                                                 <td>" . $this->listToText( $hooks ) . "</td>
266                                         </tr>\n";
267
268                         $ret .= Xml::closeElement( 'table' );
269                         return $ret;
270                 } else
271                         return '';
272         }
273
274         private function openExtType($text, $name = null) {
275                 $opt = array( 'colspan' => 3 );
276                 $out = '';
277
278                 if(!$this->firstExtOpened) {
279                         // Insert a spacing line
280                         $out .= '<tr class="sv-space">' . Xml::element( 'td', $opt ) . "</tr>\n";
281                 }
282                 $this->firstExtOpened = false;
283
284                 if($name) { $opt['id'] = "sv-$name"; }
285
286                 $out .= "<tr>" . Xml::element( 'th', $opt, $text) . "</tr>\n";
287                 return $out;
288         }
289
290         /**
291          * @return string
292          */
293         function IPInfo() {
294                 $ip =  str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
295                 return "<!-- visited from $ip -->\n" .
296                         "<span style='display:none'>visited from $ip</span>";
297         }
298
299         /**
300          * @param array $list
301          * @return string
302          */
303         function listToText( $list ) {
304                 $cnt = count( $list );
305
306                 if ( $cnt == 1 ) {
307                         // Enforce always returning a string
308                         return (string)self::arrayToString( $list[0] );
309                 } elseif ( $cnt == 0 ) {
310                         return '';
311                 } else {
312                         global $wgLang;
313                         sort( $list );
314                         return $wgLang->listToText( array_map( array( __CLASS__, 'arrayToString' ), $list ) );
315                 }
316         }
317
318         /**
319          * @param mixed $list Will convert an array to string if given and return
320          *                    the paramater unaltered otherwise
321          * @return mixed
322          */
323         static function arrayToString( $list ) {
324                 if( is_array( $list ) && count( $list ) == 1 )
325                         $list = $list[0];
326                 if( is_object( $list ) ) {
327                         $class = get_class( $list );
328                         return "($class)";
329                 } elseif ( !is_array( $list ) ) {
330                         return $list;
331                 } else {
332                         if( is_object( $list[0] ) )
333                                 $class = get_class( $list[0] );
334                         else 
335                                 $class = $list[0];
336                         return "($class, {$list[1]})";
337                 }
338         }
339
340         /**
341          * Retrieve the revision number of a Subversion working directory.
342          *
343          * @param string $dir
344          * @return mixed revision number as int, or false if not a SVN checkout
345          */
346         public static function getSvnRevision( $dir ) {
347                 // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
348                 $entries = $dir . '/.svn/entries';
349
350                 if( !file_exists( $entries ) ) {
351                         return false;
352                 }
353
354                 $content = file( $entries );
355
356                 // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
357                 if( preg_match( '/^<\?xml/', $content[0] ) ) {
358                         // subversion is release <= 1.3
359                         if( !function_exists( 'simplexml_load_file' ) ) {
360                                 // We could fall back to expat... YUCK
361                                 return false;
362                         }
363
364                         // SimpleXml whines about the xmlns...
365                         wfSuppressWarnings();
366                         $xml = simplexml_load_file( $entries );
367                         wfRestoreWarnings();
368
369                         if( $xml ) {
370                                 foreach( $xml->entry as $entry ) {
371                                         if( $xml->entry[0]['name'] == '' ) {
372                                                 // The directory entry should always have a revision marker.
373                                                 if( $entry['revision'] ) {
374                                                         return intval( $entry['revision'] );
375                                                 }
376                                         }
377                                 }
378                         }
379                         return false;
380                 } else {
381                         // subversion is release 1.4
382                         return intval( $content[3] );
383                 }
384         }
385
386         /**#@-*/
387 }