4a9fad00f9bcc45001ae363a18ee40127ac1ca95
[lhc/web/wiklou.git] / includes / SpecialVersion.php
1 <?php
2 /**#@+
3 * Give information about the version of MediaWiki, PHP, the DB and extensions
4 *
5 * @addtogroup SpecialPage
6 *
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
10 */
11
12 /**
13 * constructor
14 */
15 function wfSpecialVersion() {
16 $version = new SpecialVersion;
17 $version->execute();
18 }
19
20 class SpecialVersion {
21 private $firstExtOpened = true;
22
23 /**
24 * main()
25 */
26 function execute() {
27 global $wgOut, $wgMessageCache;
28 $wgMessageCache->loadAllMessages();
29
30 $wgOut->addHTML( '<div dir="ltr">' );
31 $wgOut->addWikiText(
32 $this->MediaWikiCredits() .
33 $this->extensionCredits() .
34 $this->wgHooks()
35 );
36 $wgOut->addHTML( $this->IPInfo() );
37 $wgOut->addHTML( '</div>' );
38 }
39
40 /**#@+
41 * @private
42 */
43
44 /**
45 * Return wiki text showing the licence information and third party
46 * software versions (apache, php, mysql).
47 * @static
48 */
49 function MediaWikiCredits() {
50 $version = self::getVersion();
51 $dbr = wfGetDB( DB_SLAVE );
52
53 $ret =
54 "__NOTOC__
55 This wiki is powered by '''[http://www.mediawiki.org/ MediaWiki]''',
56 copyright (C) 2001-2008 Magnus Manske, Brion Vibber, Lee Daniel Crocker,
57 Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason,
58 Niklas Laxström, Domas Mituzas, Rob Church and others.
59
60 MediaWiki is free software; you can redistribute it and/or modify
61 it under the terms of the GNU General Public License as published by
62 the Free Software Foundation; either version 2 of the License, or
63 (at your option) any later version.
64
65 MediaWiki is distributed in the hope that it will be useful,
66 but WITHOUT ANY WARRANTY; without even the implied warranty of
67 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68 GNU General Public License for more details.
69
70 You should have received [{{SERVER}}{{SCRIPTPATH}}/COPYING a copy of the GNU General Public License]
71 along with this program; if not, write to the Free Software
72 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
73 or [http://www.gnu.org/copyleft/gpl.html read it online]
74
75 * [http://www.mediawiki.org/ MediaWiki]: $version
76 * [http://www.php.net/ PHP]: " . phpversion() . " (" . php_sapi_name() . ")
77 * " . $dbr->getSoftwareLink() . ": " . $dbr->getServerVersion();
78
79 return str_replace( "\t\t", '', $ret ) . "\n";
80 }
81
82 /** Return a string of the MediaWiki version with SVN revision if available */
83 public static function getVersion() {
84 global $wgVersion, $IP;
85 wfProfileIn( __METHOD__ );
86 $svn = self::getSvnRevision( $IP );
87 $version = $svn ? "$wgVersion (r$svn)" : $wgVersion;
88 wfProfileOut( __METHOD__ );
89 return $version;
90 }
91
92 /** Generate wikitext showing extensions name, URL, author and description */
93 function extensionCredits() {
94 global $wgExtensionCredits, $wgExtensionFunctions, $wgParser, $wgSkinExtensionFunction;
95
96 if ( ! count( $wgExtensionCredits ) && ! count( $wgExtensionFunctions ) && ! count( $wgSkinExtensionFunction ) )
97 return '';
98
99 $extensionTypes = array(
100 'specialpage' => wfMsg( 'version-specialpages' ),
101 'parserhook' => wfMsg( 'version-parserhooks' ),
102 'variable' => wfMsg( 'version-variables' ),
103 'media' => wfMsg( 'version-mediahandlers' ),
104 'other' => wfMsg( 'version-other' ),
105 );
106 wfRunHooks( 'SpecialVersionExtensionTypes', array( &$this, &$extensionTypes ) );
107
108 $out = Xml::element( 'h2', array( 'id' => 'mw-version-ext' ), wfMsg( 'version-extensions' ) ) .
109 Xml::openElement( 'table', array( 'id' => 'sv-ext' ) );
110
111 foreach ( $extensionTypes as $type => $text ) {
112 if ( isset ( $wgExtensionCredits[$type] ) && count ( $wgExtensionCredits[$type] ) ) {
113 $out .= $this->openExtType( $text );
114
115 usort( $wgExtensionCredits[$type], array( $this, 'compare' ) );
116
117 foreach ( $wgExtensionCredits[$type] as $extension ) {
118 $out .= $this->formatCredits(
119 isset ( $extension['name'] ) ? $extension['name'] : '',
120 isset ( $extension['version'] ) ? $extension['version'] : null,
121 isset ( $extension['author'] ) ? $extension['author'] : '',
122 isset ( $extension['url'] ) ? $extension['url'] : null,
123 isset ( $extension['description'] ) ? $extension['description'] : '',
124 isset ( $extension['descriptionmsg'] ) ? $extension['descriptionmsg'] : ''
125 );
126 }
127 }
128 }
129
130 if ( count( $wgExtensionFunctions ) ) {
131 $out .= $this->openExtType( wfMsg( 'version-extension-functions' ) );
132 $out .= '<tr><td colspan="3">' . $this->listToText( $wgExtensionFunctions ) . "</td></tr>\n";
133 }
134
135 if ( $cnt = count( $tags = $wgParser->getTags() ) ) {
136 for ( $i = 0; $i < $cnt; ++$i )
137 $tags[$i] = "&lt;{$tags[$i]}&gt;";
138 $out .= $this->openExtType( wfMsg( 'version-parser-extensiontags' ) );
139 $out .= '<tr><td colspan="3">' . $this->listToText( $tags ). "</td></tr>\n";
140 }
141
142 if( $cnt = count( $fhooks = $wgParser->getFunctionHooks() ) ) {
143 $out .= $this->openExtType( wfMsg( 'version-parser-function-hooks' ) );
144 $out .= '<tr><td colspan="3">' . $this->listToText( $fhooks ) . "</td></tr>\n";
145 }
146
147 if ( count( $wgSkinExtensionFunction ) ) {
148 $out .= $this->openExtType( wfMsg( 'version-skin-extension-functions' ) );
149 $out .= '<tr><td colspan="3">' . $this->listToText( $wgSkinExtensionFunction ) . "</td></tr>\n";
150 }
151 $out .= Xml::closeElement( 'table' );
152 return $out;
153 }
154
155 /** Callback to sort extensions by type */
156 function compare( $a, $b ) {
157 global $wgLang;
158 if( $a['name'] === $b['name'] ) {
159 return 0;
160 } else {
161 return $wgLang->lc( $a['name'] ) > $wgLang->lc( $b['name'] )
162 ? 1
163 : -1;
164 }
165 }
166
167 function formatCredits( $name, $version = null, $author = null, $url = null, $description = null, $descriptionMsg = null ) {
168 $extension = isset( $url ) ? "[$url $name]" : $name;
169 $version = isset( $version ) ? "(" . wfMsg( 'version-version' ) . " $version)" : '';
170
171 # Look for a localized description
172 if( isset( $descriptionMsg ) ) {
173 $msg = wfMsg( $descriptionMsg );
174 if ( !wfEmptyMsg( $descriptionMsg, $msg ) && $msg != '' ) {
175 $description = $msg;
176 }
177 }
178
179 return "<tr>
180 <td><em>$extension $version</em></td>
181 <td>$description</td>
182 <td>" . $this->listToText( (array)$author ) . "</td>
183 </tr>\n";
184 }
185
186 /**
187 * @return string
188 */
189 function wgHooks() {
190 global $wgHooks;
191
192 if ( count( $wgHooks ) ) {
193 $myWgHooks = $wgHooks;
194 ksort( $myWgHooks );
195
196 $ret = Xml::element( 'h2', array( 'id' => 'mw-version-hooks' ), wfMsg( 'version-hooks' ) ) .
197 Xml::openElement( 'table', array( 'id' => 'sv-hooks' ) ) .
198 "<tr>
199 <th>" . wfMsg( 'version-hook-name' ) . "</th>
200 <th>" . wfMsg( 'version-hook-subscribedby' ) . "</th>
201 </tr>\n";
202
203 foreach ( $myWgHooks as $hook => $hooks )
204 $ret .= "<tr>
205 <td>$hook</td>
206 <td>" . $this->listToText( $hooks ) . "</td>
207 </tr>\n";
208
209 $ret .= Xml::closeElement( 'table' );
210 return $ret;
211 } else
212 return '';
213 }
214
215 private function openExtType($text, $name = null) {
216 $opt = array( 'colspan' => 3 );
217 $out = '';
218
219 if(!$this->firstExtOpened) {
220 // Insert a spacing line
221 $out .= '<tr class="sv-space">' . Xml::element( 'td', $opt ) . "</tr>\n";
222 }
223 $this->firstExtOpened = false;
224
225 if($name) { $opt['id'] = "sv-$name"; }
226
227 $out .= "<tr>" . Xml::element( 'th', $opt, $text) . "</tr>\n";
228 return $out;
229 }
230
231 /**
232 * @static
233 *
234 * @return string
235 */
236 function IPInfo() {
237 $ip = str_replace( '--', ' - ', htmlspecialchars( wfGetIP() ) );
238 return "<!-- visited from $ip -->\n" .
239 "<span style='display:none'>visited from $ip</span>";
240 }
241
242 /**
243 * @param array $list
244 * @return string
245 */
246 function listToText( $list ) {
247 $cnt = count( $list );
248
249 if ( $cnt == 1 ) {
250 // Enforce always returning a string
251 return (string)$this->arrayToString( $list[0] );
252 } elseif ( $cnt == 0 ) {
253 return '';
254 } else {
255 sort( $list );
256 $t = array_slice( $list, 0, $cnt - 1 );
257 $one = array_map( array( &$this, 'arrayToString' ), $t );
258 $two = $this->arrayToString( $list[$cnt - 1] );
259 $and = wfMsg( 'and' );
260
261 return implode( ', ', $one ) . " $and $two";
262 }
263 }
264
265 /**
266 * @static
267 *
268 * @param mixed $list Will convert an array to string if given and return
269 * the paramater unaltered otherwise
270 * @return mixed
271 */
272 function arrayToString( $list ) {
273 if( is_object( $list ) ) {
274 $class = get_class( $list );
275 return "($class)";
276 } elseif ( ! is_array( $list ) ) {
277 return $list;
278 } else {
279 $class = get_class( $list[0] );
280 return "($class, {$list[1]})";
281 }
282 }
283
284 /**
285 * Retrieve the revision number of a Subversion working directory.
286 *
287 * @param string $dir
288 * @return mixed revision number as int, or false if not a SVN checkout
289 */
290 public static function getSvnRevision( $dir ) {
291 // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
292 $entries = $dir . '/.svn/entries';
293
294 if( !file_exists( $entries ) ) {
295 return false;
296 }
297
298 $content = file( $entries );
299
300 // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
301 if( preg_match( '/^<\?xml/', $content[0] ) ) {
302 // subversion is release <= 1.3
303 if( !function_exists( 'simplexml_load_file' ) ) {
304 // We could fall back to expat... YUCK
305 return false;
306 }
307
308 // SimpleXml whines about the xmlns...
309 wfSuppressWarnings();
310 $xml = simplexml_load_file( $entries );
311 wfRestoreWarnings();
312
313 if( $xml ) {
314 foreach( $xml->entry as $entry ) {
315 if( $xml->entry[0]['name'] == '' ) {
316 // The directory entry should always have a revision marker.
317 if( $entry['revision'] ) {
318 return intval( $entry['revision'] );
319 }
320 }
321 }
322 }
323 return false;
324 } else {
325 // subversion is release 1.4
326 return intval( $content[3] );
327 }
328 }
329
330 /**#@-*/
331 }
332
333 /**#@-*/
334
335