sending the content language code as Content-language
[lhc/web/wiklou.git] / includes / SpecialPage.php
1 <?php
2 /**
3 * SpecialPage: handling special pages and lists thereof
4 * $wgSpecialPages is a list of all SpecialPage objects. These objects are
5 * either instances of SpecialPage or a sub-class thereof. They have an
6 * execute() method, which sends the HTML for the special page to $wgOut.
7 * The parent class has an execute() method which distributes the call to
8 * the historical global functions. Additionally, execute() also checks if the
9 * user has the necessary access privileges and bails out if not.
10 *
11 * To add a special page at run-time, use SpecialPage::addPage().
12 * DO NOT manipulate this array at run-time.
13 *
14 * @package MediaWiki
15 */
16
17 /**
18 *
19 */
20 global $wgSpecialPages;
21
22 /**
23 * @access private
24 */
25 $wgSpecialPages = array(
26 'DoubleRedirects' => new UnlistedSpecialPage ( 'DoubleRedirects' ),
27 'BrokenRedirects' => new UnlistedSpecialPage ( 'BrokenRedirects' ),
28 'Disambiguations' => new UnlistedSpecialPage ( 'Disambiguations' ),
29
30 'Userlogin' => new SpecialPage( 'Userlogin' ),
31 'Userlogout' => new UnlistedSpecialPage( 'Userlogout' ),
32 'Preferences' => new SpecialPage( 'Preferences' ),
33 'Watchlist' => new SpecialPage( 'Watchlist' ),
34 'Recentchanges' => new SpecialPage( 'Recentchanges' ),
35 'Upload' => new SpecialPage( 'Upload' ),
36 'Imagelist' => new SpecialPage( 'Imagelist' ),
37 'Newimages' => new SpecialPage( 'Newimages' ),
38 'Listusers' => new SpecialPage( 'Listusers' ),
39 'Listadmins' => new SpecialPage( 'Listadmins' ),
40 'Statistics' => new SpecialPage( 'Statistics' ),
41 'Randompage' => new SpecialPage( 'Randompage' ),
42 'Lonelypages' => new SpecialPage( 'Lonelypages' ),
43 'Uncategorizedpages'=> new SpecialPage( 'Uncategorizedpages' ),
44 'Unusedimages' => new SpecialPage( 'Unusedimages' )
45 );
46 global $wgDisableCounters;
47 if( !$wgDisableCounters ) {
48 $wgSpecialPages['Popularpages'] = new SpecialPage( 'Popularpages' );
49 }
50 $wgSpecialPages = array_merge($wgSpecialPages, array (
51 'Wantedpages' => new SpecialPage( 'Wantedpages' ),
52 'Shortpages' => new SpecialPage( 'Shortpages' ),
53 'Longpages' => new SpecialPage( 'Longpages' ),
54 'Newpages' => new SpecialPage( 'Newpages' ),
55 'Ancientpages' => new SpecialPage( 'Ancientpages' ),
56 'Deadendpages' => new SpecialPage( 'Deadendpages' ),
57 'Allpages' => new SpecialPage( 'Allpages' ),
58 'Ipblocklist' => new SpecialPage( 'Ipblocklist' ),
59 'Maintenance' => new SpecialPage( 'Maintenance' ),
60 'Specialpages' => new UnlistedSpecialPage( 'Specialpages' ),
61 'Contributions' => new UnlistedSpecialPage( 'Contributions' ),
62 'Emailuser' => new UnlistedSpecialPage( 'Emailuser' ),
63 'Whatlinkshere' => new UnlistedSpecialPage( 'Whatlinkshere' ),
64 'Recentchangeslinked' => new UnlistedSpecialPage( 'Recentchangeslinked' ),
65 'Movepage' => new UnlistedSpecialPage( 'Movepage' ),
66 'Blockme' => new UnlistedSpecialPage( 'Blockme' ),
67 'Geo' => new UnlistedSpecialPage( 'Geo' ),
68 'Validate' => new UnlistedSpecialPage( 'Validate' ),
69 'Booksources' => new SpecialPage( 'Booksources' ),
70 'Categories' => new SpecialPage( 'Categories' ),
71 'Export' => new SpecialPage( 'Export' ),
72 'Version' => new SpecialPage( 'Version' ),
73 'Allmessages' => new SpecialPage( 'Allmessages' ),
74 'Search' => new UnlistedSpecialPage( 'Search' ),
75 'Log' => new SpecialPage( 'Log' ),
76 'Blockip' => new SpecialPage( 'Blockip', 'sysop' ),
77 'Asksql' => new SpecialPage( 'Asksql', 'sysop' ),
78 'Undelete' => new SpecialPage( 'Undelete', 'sysop' ),
79 'Makesysop' => new SpecialPage( 'Makesysop', 'sysop' ),
80
81 # Special:Import is half-written
82 # "Import" => new SpecialPage( "Import", "sysop" ),
83 'Lockdb' => new SpecialPage( 'Lockdb', 'developer' ),
84 'Unlockdb' => new SpecialPage( 'Unlockdb', 'developer' ),
85 // "Sitesettings" => new SpecialPage( "Sitesettings" )
86 ));
87
88 /**
89 * Parent special page class, also static functions for handling the special
90 * page list
91 * @package MediaWiki
92 */
93 class SpecialPage
94 {
95 /**#@+
96 * @access private
97 */
98 /**
99 * The name of the class, used in the URL.
100 * Also used for the default <h1> heading, @see getDescription()
101 */
102 var $mName;
103 /**
104 * Minimum user level required to access this page, or "" for anyone.
105 * Also used to categorise the pages in Special:Specialpages
106 */
107 var $mRestriction;
108 /**
109 * Listed in Special:Specialpages?
110 */
111 var $mListed;
112 /**
113 * Function name called by the default execute()
114 */
115 var $mFunction;
116 /**
117 * File which needs to be included before the function above can be called
118 */
119 var $mFile;
120 /**#@- */
121
122 /**
123 * Add a page to the list of valid special pages
124 * $obj->execute() must send HTML to $wgOut then return
125 * Use this for a special page extension
126 * @static
127 */
128 function addPage( &$obj ) {
129 global $wgSpecialPages;
130 $wgSpecialPages[$obj->mName] = $obj;
131 }
132
133 /**
134 * Remove a special page from the list
135 * Occasionally used to disable expensive or dangerous special pages
136 * @static
137 */
138 function removePage( $name ) {
139 global $wgSpecialPages;
140 unset( $wgSpecialPages[$name] );
141 }
142
143 /**
144 * Find the object with a given name and return it (or NULL)
145 * @static
146 * @param string $name
147 */
148 function &getPage( $name ) {
149 global $wgSpecialPages;
150 if ( array_key_exists( $name, $wgSpecialPages ) ) {
151 return $wgSpecialPages[$name];
152 } else {
153 return NULL;
154 }
155 }
156
157 /**
158 * Return categorised listable special pages
159 * Returns a 2d array where the first index is the restriction name
160 * @static
161 */
162 function getPages() {
163 global $wgSpecialPages;
164 $pages = array(
165 '' => array(),
166 'sysop' => array(),
167 'developer' => array()
168 );
169
170 foreach ( $wgSpecialPages as $name => $page ) {
171 if ( $page->isListed() ) {
172 $pages[$page->getRestriction()][$page->getName()] =& $wgSpecialPages[$name];
173 }
174 }
175 return $pages;
176 }
177
178 /**
179 * Execute a special page path.
180 * The path may contain parameters, e.g. Special:Name/Params
181 * Extracts the special page name and call the execute method, passing the parameters
182 *
183 * @param $title should be a title object
184 */
185 function executePath( &$title ) {
186 global $wgSpecialPages, $wgOut, $wgTitle;
187
188 $bits = split( "/", $title->getDBkey(), 2 );
189 $name = $bits[0];
190 if( empty( $bits[1] ) ) {
191 $par = NULL;
192 } else {
193 $par = $bits[1];
194 }
195
196 $page =& SpecialPage::getPage( $name );
197 if ( is_null( $page ) ) {
198 $wgOut->setArticleRelated( false );
199 $wgOut->setRobotpolicy( "noindex,follow" );
200 $wgOut->errorpage( "nosuchspecialpage", "nospecialpagetext" );
201 } else {
202 if($par !== NULL) {
203 $wgTitle = Title::makeTitle( NS_SPECIAL, $name );
204 } else {
205 $wgTitle = $title;
206 }
207
208 $page->execute( $par );
209 }
210 }
211
212 /**
213 * Default constructor for special pages
214 * Derivative classes should call this from their constructor
215 * Note that if the user does not have the required level, an error message will
216 * be displayed by the default execute() method, without the global function ever
217 * being called.
218 *
219 * If you override execute(), you can recover the default behaviour with userCanExecute()
220 * and displayRestrictionError()
221 *
222 * @param string $name Name of the special page, as seen in links and URLs
223 * @param string $restriction Minimum user level required, e.g. "sysop" or "developer".
224 * @param boolean $listed Whether the page is listed in Special:Specialpages
225 * @param string $function Function called by execute(). By default it is constructed from $name
226 * @param string $file File which is included by execute(). It is also constructed from $name by default
227 */
228 function SpecialPage( $name = '', $restriction = '', $listed = true, $function = false, $file = 'default' ) {
229 $this->mName = $name;
230 $this->mRestriction = $restriction;
231 $this->mListed = $listed;
232 if ( $function == false ) {
233 $this->mFunction = 'wfSpecial'.$name;
234 } else {
235 $this->mFunction = $function;
236 }
237 if ( $file === 'default' ) {
238 $this->mFile = "Special{$name}.php";
239 } else {
240 $this->mFile = $file;
241 }
242 }
243
244 # Accessor functions, see the descriptions of the associated variables above
245 function getName() { return $this->mName; }
246 function getRestriction() { return $this->mRestriction; }
247 function isListed() { return $this->mListed; }
248
249 /**
250 * Checks if the given user (identified by an object) can execute this
251 * special page (as defined by $mRestriction)
252 */
253 function userCanExecute( &$user ) {
254 if ( $this->mRestriction == "" ) {
255 return true;
256 } else {
257 if ( in_array( $this->mRestriction, $user->getRights() ) ) {
258 return true;
259 } else {
260 return false;
261 }
262 }
263 }
264
265 /**
266 * Output an error message telling the user what access level they have to have
267 */
268 function displayRestrictionError() {
269 global $wgOut;
270 if ( $this->mRestriction == "developer" ) {
271 $wgOut->developerRequired();
272 } else {
273 $wgOut->sysopRequired();
274 }
275 }
276
277 /**
278 * Sets headers - this should be called from the execute() method of all derived classes!
279 */
280 function setHeaders() {
281 global $wgOut;
282 $wgOut->setArticleRelated( false );
283 $wgOut->setRobotPolicy( "noindex,follow" );
284 $wgOut->setPageTitle( $this->getDescription() );
285 }
286
287 /**
288 * Default execute method
289 * Checks user permissions, calls the function given in mFunction
290 */
291 function execute( $par ) {
292 global $wgUser, $wgOut, $wgTitle;
293
294 $this->setHeaders();
295
296 if ( $this->userCanExecute( $wgUser ) ) {
297 if ( $this->mFile ) {
298 require_once( $this->mFile );
299 }
300 $func = $this->mFunction;
301 $func( $par );
302 } else {
303 $this->displayRestrictionError();
304 }
305 }
306
307 # Returns the name that goes in the <h1> in the special page itself, and also the name that
308 # will be listed in Special:Specialpages
309 #
310 # Derived classes can override this, but usually it is easier to keep the default behaviour.
311 # Messages can be added at run-time, see MessageCache.php
312 function getDescription() {
313 return wfMsg( strtolower( $this->mName ) );
314 }
315
316 /**
317 * Get a self-referential title object
318 */
319 function getTitle() {
320 return Title::makeTitle( NS_SPECIAL, $this->mName );
321 }
322
323 /**
324 * Set whether this page is listed in Special:Specialpages, at run-time
325 */
326 function setListed( $listed ) {
327 return wfSetVar( $this->mListed, $listed );
328 }
329 }
330
331 /**
332 * Shortcut to construct a special page which is unlisted by default
333 * @package MediaWiki
334 */
335 class UnlistedSpecialPage extends SpecialPage
336 {
337 function UnlistedSpecialPage( $name, $restriction = '', $function = false, $file = 'default' ) {
338 SpecialPage::SpecialPage( $name, $restriction, false, $function, $file );
339 }
340 }