Commit | Line | Data |
---|---|---|
64a19c3d ML |
1 | <?php |
2 | ||
3 | if ( !defined( 'MEDIAWIKI' ) ) { | |
4 | die( "This file is part of MediaWiki, it is not a valid entry point\n" ); | |
5 | } | |
6 | ||
7 | require_once( 'includes/cbt/CBTProcessor.php' ); | |
8 | require_once( 'includes/cbt/CBTCompiler.php' ); | |
9 | require_once( 'includes/SkinTemplate.php' ); | |
10 | ||
11 | /** | |
12 | * MonoBook clone using the new dependency-tracking template processor. | |
13 | * EXPERIMENTAL - use only for testing and profiling at this stage. | |
14 | * | |
15 | * See includes/cbt/README for an explanation. | |
16 | * | |
17 | * The main thing that's missing is cache invalidation, on change of: | |
18 | * * messages | |
19 | * * user preferences | |
20 | * * source template | |
21 | * * source code and configuration files | |
22 | * | |
23 | * The other thing is that lots of dependencies that are declared in the callbacks | |
24 | * are not intelligently handled. There's some room for improvement there. | |
25 | * | |
26 | * The class is derived from SkinTemplate, but that's only temporary. Eventually | |
27 | * it'll be derived from Skin, and I've avoided using SkinTemplate functions as | |
28 | * much as possible. In fact, the only SkinTemplate dependencies I know of at the | |
29 | * moment are the functions to generate the gen=css and gen=js files. | |
30 | * | |
31 | */ | |
32 | class SkinMonoBookCBT extends SkinTemplate { | |
33 | var $mOut, $mTitle; | |
34 | var $mStyleName = 'monobook'; | |
35 | var $mCompiling = false; | |
36 | var $mFunctionCache = array(); | |
37 | ||
38 | /****************************************************** | |
39 | * General functions * | |
40 | ******************************************************/ | |
41 | ||
42 | /** Execute the template and write out the result */ | |
43 | function outputPage( &$out ) { | |
44 | echo $this->execute( $out ); | |
45 | } | |
46 | ||
47 | function execute( &$out ) { | |
48 | global $wgTitle, $wgStyleDirectory, $wgParserCacheType; | |
49 | $fname = 'SkinMonoBookCBT::execute'; | |
50 | wfProfileIn( $fname ); | |
51 | wfProfileIn( "$fname-setup" ); | |
52 | Skin::initPage( $out ); | |
53 | ||
54 | $this->mOut =& $out; | |
55 | $this->mTitle =& $wgTitle; | |
56 | ||
57 | $sourceFile = "$wgStyleDirectory/MonoBook.tpl"; | |
58 | ||
59 | wfProfileOut( "$fname-setup" ); | |
60 | ||
61 | if ( $wgParserCacheType == CACHE_NONE ) { | |
62 | $template = file_get_contents( $sourceFile ); | |
63 | $text = $this->executeTemplate( $template ); | |
64 | } else { | |
65 | $compiled = $this->getCompiledTemplate( $sourceFile ); | |
66 | ||
67 | wfProfileIn( "$fname-eval" ); | |
68 | $text = eval( $compiled ); | |
69 | wfProfileOut( "$fname-eval" ); | |
70 | } | |
71 | wfProfileOut( $fname ); | |
72 | return $text; | |
73 | } | |
74 | ||
75 | function getCompiledTemplate( $sourceFile ) { | |
76 | global $wgDBname, $wgMemc, $wgRequest, $wgUser, $parserMemc; | |
77 | $fname = 'SkinMonoBookCBT::getCompiledTemplate'; | |
78 | ||
79 | $expiry = 3600; | |
80 | ||
81 | // Sandbox template execution | |
82 | if ( $this->mCompiling ) { | |
83 | return; | |
84 | } | |
85 | ||
86 | wfProfileIn( $fname ); | |
87 | ||
88 | // Is the request an ordinary page view? | |
89 | if ( $wgRequest->wasPosted() || | |
90 | count( array_diff( array_keys( $_GET ), array( 'title', 'useskin', 'recompile' ) ) ) != 0 ) | |
91 | { | |
92 | $type = 'nonview'; | |
93 | } else { | |
94 | $type = 'view'; | |
95 | } | |
96 | ||
97 | // Per-user compiled template | |
98 | // Put all logged-out users on the same cache key | |
99 | $cacheKey = "$wgDBname:monobookcbt:$type:" . $wgUser->getId(); | |
100 | ||
101 | $recompile = $wgRequest->getVal( 'recompile' ); | |
102 | if ( $recompile == 'user' ) { | |
103 | $recompileUser = true; | |
104 | $recompileGeneric = false; | |
105 | } elseif ( $recompile ) { | |
106 | $recompileUser = true; | |
107 | $recompileGeneric = true; | |
108 | } else { | |
109 | $recompileUser = false; | |
110 | $recompileGeneric = false; | |
111 | } | |
112 | ||
113 | if ( !$recompileUser ) { | |
114 | $php = $parserMemc->get( $cacheKey ); | |
115 | } | |
116 | if ( $recompileUser || !$php ) { | |
117 | if ( $wgUser->isLoggedIn() ) { | |
118 | // Perform staged compilation | |
119 | // First compile a generic template for all logged-in users | |
120 | $genericKey = "$wgDBname:monobookcbt:$type:loggedin"; | |
121 | if ( !$recompileGeneric ) { | |
122 | $template = $parserMemc->get( $genericKey ); | |
123 | } | |
124 | if ( $recompileGeneric || !$template ) { | |
125 | $template = file_get_contents( $sourceFile ); | |
126 | $ignore = array( 'loggedin', '!loggedin dynamic' ); | |
127 | if ( $type == 'view' ) { | |
128 | $ignore[] = 'nonview dynamic'; | |
129 | } | |
130 | $template = $this->compileTemplate( $template, $ignore ); | |
131 | $parserMemc->set( $genericKey, $template, $expiry ); | |
132 | } | |
133 | } else { | |
134 | $template = file_get_contents( $sourceFile ); | |
135 | } | |
136 | ||
137 | $ignore = array( 'lang', 'loggedin', 'user' ); | |
138 | if ( $wgUser->isLoggedIn() ) { | |
139 | $ignore[] = '!loggedin dynamic'; | |
140 | } else { | |
141 | $ignore[] = 'loggedin dynamic'; | |
142 | } | |
143 | if ( $type == 'view' ) { | |
144 | $ignore[] = 'nonview dynamic'; | |
145 | } | |
146 | $compiled = $this->compileTemplate( $template, $ignore ); | |
147 | ||
148 | // Reduce whitespace | |
149 | // This is done here instead of in CBTProcessor because we can be | |
150 | // more sure it is safe here. | |
151 | $compiled = preg_replace( '/^[ \t]+/m', '', $compiled ); | |
152 | $compiled = preg_replace( '/[\r\n]+/', "\n", $compiled ); | |
153 | ||
154 | // Compile to PHP | |
155 | $compiler = new CBTCompiler( $compiled ); | |
156 | $ret = $compiler->compile(); | |
157 | if ( $ret !== true ) { | |
158 | echo $ret; | |
159 | wfErrorExit(); | |
160 | } | |
161 | $php = $compiler->generatePHP( '$this' ); | |
162 | ||
163 | $parserMemc->set( $cacheKey, $php, $expiry ); | |
164 | } | |
165 | wfProfileOut( $fname ); | |
166 | return $php; | |
167 | } | |
168 | ||
169 | function compileTemplate( $template, $ignore ) { | |
170 | $tp = new CBTProcessor( $template, $this, $ignore ); | |
171 | $tp->mFunctionCache = $this->mFunctionCache; | |
172 | ||
173 | $this->mCompiling = true; | |
174 | $compiled = $tp->compile(); | |
175 | $this->mCompiling = false; | |
176 | ||
177 | if ( $tp->getLastError() ) { | |
178 | // If there was a compile error, don't save the template | |
179 | // Instead just print the error and exit | |
180 | echo $compiled; | |
181 | wfErrorExit(); | |
182 | } | |
183 | $this->mFunctionCache = $tp->mFunctionCache; | |
184 | return $compiled; | |
185 | } | |
186 | ||
187 | function executeTemplate( $template ) { | |
188 | $fname = 'SkinMonoBookCBT::executeTemplate'; | |
189 | wfProfileIn( $fname ); | |
190 | $tp = new CBTProcessor( $template, $this ); | |
191 | $tp->mFunctionCache = $this->mFunctionCache; | |
192 | ||
193 | $this->mCompiling = true; | |
194 | $text = $tp->execute(); | |
195 | $this->mCompiling = false; | |
196 | ||
197 | $this->mFunctionCache = $tp->mFunctionCache; | |
198 | wfProfileOut( $fname ); | |
199 | return $text; | |
200 | } | |
201 | ||
202 | /****************************************************** | |
203 | * Callbacks * | |
204 | ******************************************************/ | |
205 | ||
206 | function lang() { return $GLOBALS['wgContLanguageCode']; } | |
207 | ||
208 | function dir() { | |
209 | global $wgContLang; | |
210 | return $wgContLang->isRTL() ? 'rtl' : 'ltr'; | |
211 | } | |
212 | ||
213 | function mimetype() { return $GLOBALS['wgMimeType']; } | |
214 | function charset() { return $GLOBALS['wgOutputEncoding']; } | |
215 | function headlinks() { | |
216 | return cbt_value( $this->mOut->getHeadLinks(), 'dynamic' ); | |
217 | } | |
218 | function headscripts() { | |
219 | return cbt_value( $this->mOut->getScript(), 'dynamic' ); | |
220 | } | |
221 | ||
222 | function pagetitle() { | |
223 | return cbt_value( $this->mOut->getHTMLTitle(), array( 'title', 'lang' ) ); | |
224 | } | |
225 | ||
226 | function stylepath() { return $GLOBALS['wgStylePath']; } | |
227 | function stylename() { return $this->mStyleName; } | |
228 | ||
229 | function notprintable() { | |
230 | global $wgRequest; | |
231 | return cbt_value( !$wgRequest->getBool( 'printable' ), 'nonview dynamic' ); | |
232 | } | |
233 | ||
234 | function jsmimetype() { return $GLOBALS['wgJsMimeType']; } | |
235 | ||
236 | function jsvarurl() { | |
237 | global $wgUseSiteJs, $wgUser; | |
238 | if ( !$wgUseSiteJs ) return ''; | |
239 | ||
240 | if ( $wgUser->isLoggedIn() ) { | |
241 | $url = self::makeUrl( '-','action=raw&smaxage=0&gen=js' ); | |
242 | } else { | |
243 | $url = self::makeUrl( '-','action=raw&gen=js' ); | |
244 | } | |
245 | return cbt_value( $url, 'loggedin' ); | |
246 | } | |
247 | ||
248 | function pagecss() { | |
249 | global $wgHooks; | |
250 | ||
251 | $out = false; | |
252 | wfRunHooks( 'SkinTemplateSetupPageCss', array( &$out ) ); | |
253 | ||
254 | // Unknown dependencies | |
255 | return cbt_value( $out, 'dynamic' ); | |
256 | } | |
257 | ||
258 | function usercss() { | |
259 | if ( $this->isCssPreview() ) { | |
260 | global $wgRequest; | |
261 | $usercss = $this->makeStylesheetCdata( $wgRequest->getText('wpTextbox1') ); | |
262 | } else { | |
263 | $usercss = $this->makeStylesheetLink( self::makeUrl($this->getUserPageText() . | |
264 | '/'.$this->mStyleName.'.css', 'action=raw&ctype=text/css' ) ); | |
265 | } | |
266 | ||
267 | // Dynamic when not an ordinary page view, also depends on the username | |
268 | return cbt_value( $usercss, array( 'nonview dynamic', 'user' ) ); | |
269 | } | |
270 | ||
271 | function sitecss() { | |
272 | global $wgUseSiteCss; | |
273 | if ( !$wgUseSiteCss ) { | |
274 | return ''; | |
275 | } | |
276 | ||
277 | global $wgSquidMaxage, $wgContLang, $wgStylePath; | |
278 | ||
279 | $query = "action=raw&ctype=text/css&smaxage=$wgSquidMaxage"; | |
280 | ||
281 | $sitecss = ''; | |
282 | if ( $wgContLang->isRTL() ) { | |
283 | $sitecss .= $this->makeStylesheetLink( $wgStylePath . '/' . $this->mStyleName . '/rtl.css' ) . "\n"; | |
284 | } | |
285 | ||
286 | $sitecss .= $this->makeStylesheetLink( self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI ) ) . "\n"; | |
287 | $sitecss .= $this->makeStylesheetLink( self::makeNSUrl( ucfirst( $this->mStyleName ) . '.css', $query, NS_MEDIAWIKI ) ) . "\n"; | |
288 | ||
289 | // No deps | |
290 | return $sitecss; | |
291 | } | |
292 | ||
293 | function gencss() { | |
294 | global $wgUseSiteCss; | |
295 | if ( !$wgUseSiteCss ) return ''; | |
296 | ||
297 | global $wgSquidMaxage, $wgUser, $wgAllowUserCss; | |
298 | if ( $this->isCssPreview() ) { | |
299 | $siteargs = '&smaxage=0&maxage=0'; | |
300 | } else { | |
301 | $siteargs = '&maxage=' . $wgSquidMaxage; | |
302 | } | |
303 | if ( $wgAllowUserCss && $wgUser->isLoggedIn() ) { | |
304 | $siteargs .= '&ts={user_touched}'; | |
305 | $isTemplate = true; | |
306 | } else { | |
307 | $isTemplate = false; | |
308 | } | |
309 | ||
310 | $link = $this->makeStylesheetLink( self::makeUrl('-','action=raw&gen=css' . $siteargs) ) . "\n"; | |
311 | ||
312 | if ( $wgAllowUserCss ) { | |
313 | $deps = 'loggedin'; | |
314 | } else { | |
315 | $deps = array(); | |
316 | } | |
317 | return cbt_value( $link, $deps, $isTemplate ); | |
318 | } | |
319 | ||
320 | function user_touched() { | |
321 | global $wgUser; | |
322 | return cbt_value( $wgUser->mTouched, 'dynamic' ); | |
323 | } | |
324 | ||
325 | function userjs() { | |
326 | global $wgAllowUserJs, $wgJsMimeType; | |
327 | if ( !$wgAllowUserJs ) return ''; | |
328 | ||
329 | if ( $this->isJsPreview() ) { | |
330 | $url = ''; | |
331 | } else { | |
332 | $url = self::makeUrl($this->getUserPageText().'/'.$this->mStyleName.'.js', 'action=raw&ctype='.$wgJsMimeType.'&dontcountme=s'); | |
333 | } | |
334 | return cbt_value( $url, array( 'nonview dynamic', 'user' ) ); | |
335 | } | |
336 | ||
337 | function userjsprev() { | |
338 | global $wgAllowUserJs, $wgRequest; | |
339 | if ( !$wgAllowUserJs ) return ''; | |
340 | if ( $this->isJsPreview() ) { | |
341 | $js = '/*<![CDATA[*/ ' . $wgRequest->getText('wpTextbox1') . ' /*]]>*/'; | |
342 | } else { | |
343 | $js = ''; | |
344 | } | |
345 | return cbt_value( $js, array( 'nonview dynamic' ) ); | |
346 | } | |
347 | ||
348 | function trackbackhtml() { | |
349 | global $wgUseTrackbacks; | |
350 | if ( !$wgUseTrackbacks ) return ''; | |
351 | ||
352 | if ( $this->mOut->isArticleRelated() ) { | |
353 | $tb = $this->mTitle->trackbackRDF(); | |
354 | } else { | |
355 | $tb = ''; | |
356 | } | |
357 | return cbt_value( $tb, 'dynamic' ); | |
358 | } | |
359 | ||
360 | function body_ondblclick() { | |
361 | global $wgUser; | |
362 | if( $this->isEditable() && $wgUser->getOption("editondblclick") ) { | |
363 | $js = 'document.location = "' . $this->getEditUrl() .'";'; | |
364 | } else { | |
365 | $js = ''; | |
366 | } | |
367 | ||
368 | if ( User::getDefaultOption('editondblclick') ) { | |
369 | return cbt_value( $js, 'user', 'title' ); | |
370 | } else { | |
371 | // Optimise away for logged-out users | |
372 | return cbt_value( $js, 'loggedin dynamic' ); | |
373 | } | |
374 | } | |
375 | ||
376 | function body_onload() { | |
377 | global $wgUser; | |
378 | if ( $this->isEditable() && $wgUser->getOption( 'editsectiononrightclick' ) ) { | |
379 | $js = 'setupRightClickEdit()'; | |
380 | } else { | |
381 | $js = ''; | |
382 | } | |
383 | return cbt_value( $js, 'loggedin dynamic' ); | |
384 | } | |
385 | ||
386 | function nsclass() { | |
387 | return cbt_value( 'ns-' . $this->mTitle->getNamespace(), 'title' ); | |
388 | } | |
389 | ||
390 | function sitenotice() { | |
391 | // Perhaps this could be given special dependencies using our knowledge of what | |
392 | // wfGetSiteNotice() depends on. | |
393 | return cbt_value( wfGetSiteNotice(), 'dynamic' ); | |
394 | } | |
395 | ||
396 | function title() { | |
397 | return cbt_value( $this->mOut->getPageTitle(), array( 'title', 'lang' ) ); | |
398 | } | |
399 | ||
400 | function title_urlform() { | |
401 | return cbt_value( $this->getThisTitleUrlForm(), 'title' ); | |
402 | } | |
403 | ||
404 | function title_userurl() { | |
405 | return cbt_value( urlencode( $this->mTitle->getDBkey() ), 'title' ); | |
406 | } | |
407 | ||
408 | function subtitle() { | |
409 | $subpagestr = $this->subPageSubtitle(); | |
410 | if ( !empty( $subpagestr ) ) { | |
411 | $s = '<span class="subpages">'.$subpagestr.'</span>'.$this->mOut->getSubtitle(); | |
412 | } else { | |
413 | $s = $this->mOut->getSubtitle(); | |
414 | } | |
415 | return cbt_value( $s, array( 'title', 'nonview dynamic' ) ); | |
416 | } | |
417 | ||
418 | function undelete() { | |
419 | return cbt_value( $this->getUndeleteLink(), array( 'title', 'lang' ) ); | |
420 | } | |
421 | ||
422 | function newtalk() { | |
423 | global $wgUser, $wgDBname; | |
424 | $newtalks = $wgUser->getNewMessageLinks(); | |
425 | ||
426 | if (count($newtalks) == 1 && $newtalks[0]["wiki"] === $wgDBname) { | |
427 | $usertitle = $this->getUserPageTitle(); | |
428 | $usertalktitle = $usertitle->getTalkPage(); | |
429 | if( !$usertalktitle->equals( $this->mTitle ) ) { | |
430 | $ntl = wfMsg( 'youhavenewmessages', | |
431 | $this->makeKnownLinkObj( | |
432 | $usertalktitle, | |
433 | wfMsgHtml( 'newmessageslink' ), | |
434 | 'redirect=no' | |
435 | ), | |
436 | $this->makeKnownLinkObj( | |
437 | $usertalktitle, | |
438 | wfMsgHtml( 'newmessagesdifflink' ), | |
439 | 'diff=cur' | |
440 | ) | |
441 | ); | |
442 | # Disable Cache | |
443 | $this->mOut->setSquidMaxage(0); | |
444 | } | |
445 | } else if (count($newtalks)) { | |
446 | $sep = str_replace("_", " ", wfMsgHtml("newtalkseparator")); | |
447 | $msgs = array(); | |
448 | foreach ($newtalks as $newtalk) { | |
449 | $msgs[] = wfElement("a", | |
450 | array('href' => $newtalk["link"]), $newtalk["wiki"]); | |
451 | } | |
452 | $parts = implode($sep, $msgs); | |
453 | $ntl = wfMsgHtml('youhavenewmessagesmulti', $parts); | |
454 | $this->mOut->setSquidMaxage(0); | |
455 | } else { | |
456 | $ntl = ''; | |
457 | } | |
458 | return cbt_value( $ntl, 'dynamic' ); | |
459 | } | |
460 | ||
461 | function showjumplinks() { | |
462 | global $wgUser; | |
463 | return cbt_value( $wgUser->getOption( 'showjumplinks' ) ? 'true' : '', 'user' ); | |
464 | } | |
465 | ||
466 | function bodytext() { | |
467 | return cbt_value( $this->mOut->getHTML(), 'dynamic' ); | |
468 | } | |
469 | ||
470 | function catlinks() { | |
471 | if ( !isset( $this->mCatlinks ) ) { | |
472 | $this->mCatlinks = $this->getCategories(); | |
473 | } | |
474 | return cbt_value( $this->mCatlinks, 'dynamic' ); | |
475 | } | |
476 | ||
477 | function extratabs( $itemTemplate ) { | |
478 | global $wgContLang, $wgDisableLangConversion; | |
479 | ||
480 | $etpl = cbt_escape( $itemTemplate ); | |
481 | ||
482 | /* show links to different language variants */ | |
483 | $variants = $wgContLang->getVariants(); | |
484 | $s = ''; | |
485 | if ( !$wgDisableLangConversion && count( $wgContLang->getVariants() ) > 1 ) { | |
486 | $vcount=0; | |
487 | foreach ( $variants as $code ) { | |
488 | $name = $wgContLang->getVariantname( $code ); | |
489 | if ( $name == 'disable' ) { | |
490 | continue; | |
491 | } | |
492 | $code = cbt_escape( $code ); | |
493 | $name = cbt_escape( $name ); | |
494 | $s .= "{ca_variant {{$code}} {{$name}} {{$vcount}} {{$etpl}}}\n"; | |
495 | $vcount ++; | |
496 | } | |
497 | } | |
498 | return cbt_value( $s, array(), true ); | |
499 | } | |
500 | ||
501 | function is_special() { return cbt_value( $this->mTitle->getNamespace() == NS_SPECIAL, 'title' ); } | |
502 | function can_edit() { return cbt_value( (string)($this->mTitle->userCan( 'edit' )), 'dynamic' ); } | |
503 | function can_move() { return cbt_value( (string)($this->mTitle->userCan( 'move' )), 'dynamic' ); } | |
504 | function is_talk() { return cbt_value( (string)($this->mTitle->isTalkPage()), 'title' ); } | |
505 | function is_protected() { return cbt_value( (string)$this->mTitle->isProtected(), 'dynamic' ); } | |
506 | function nskey() { return cbt_value( $this->mTitle->getNamespaceKey(), 'title' ); } | |
507 | ||
508 | function request_url() { | |
509 | global $wgRequest; | |
510 | return cbt_value( $wgRequest->getRequestURL(), 'dynamic' ); | |
511 | } | |
512 | ||
513 | function subject_url() { | |
514 | $title = $this->getSubjectPage(); | |
515 | if ( $title->exists() ) { | |
516 | $url = $title->getLocalUrl(); | |
517 | } else { | |
518 | $url = $title->getLocalUrl( 'action=edit' ); | |
519 | } | |
520 | return cbt_value( $url, 'title' ); | |
521 | } | |
522 | ||
523 | function talk_url() { | |
524 | $title = $this->getTalkPage(); | |
525 | if ( $title->exists() ) { | |
526 | $url = $title->getLocalUrl(); | |
527 | } else { | |
528 | $url = $title->getLocalUrl( 'action=edit' ); | |
529 | } | |
530 | return cbt_value( $url, 'title' ); | |
531 | } | |
532 | ||
533 | function edit_url() { | |
534 | return cbt_value( $this->getEditUrl(), array( 'title', 'nonview dynamic' ) ); | |
535 | } | |
536 | ||
537 | function move_url() { | |
538 | return cbt_value( $this->makeSpecialParamUrl( 'Movepage' ), array(), true ); | |
539 | } | |
540 | ||
541 | function localurl( $query ) { | |
542 | return cbt_value( $this->mTitle->getLocalURL( $query ), 'title' ); | |
543 | } | |
544 | ||
545 | function selecttab( $tab, $extraclass = '' ) { | |
546 | if ( !isset( $this->mSelectedTab ) ) { | |
547 | $prevent_active_tabs = false ; | |
548 | wfRunHooks( 'SkinTemplatePreventOtherActiveTabs', array( &$this , &$preventActiveTabs ) ); | |
549 | ||
550 | $actionTabs = array( | |
551 | 'edit' => 'edit', | |
552 | 'submit' => 'edit', | |
553 | 'history' => 'history', | |
554 | 'protect' => 'protect', | |
555 | 'unprotect' => 'protect', | |
556 | 'delete' => 'delete', | |
557 | 'watch' => 'watch', | |
558 | 'unwatch' => 'watch', | |
559 | ); | |
560 | if ( $preventActiveTabs ) { | |
561 | $this->mSelectedTab = false; | |
562 | } else { | |
563 | $action = $this->getAction(); | |
564 | $section = $this->getSection(); | |
565 | ||
566 | if ( isset( $actionTabs[$action] ) ) { | |
567 | $this->mSelectedTab = $actionTabs[$action]; | |
568 | ||
569 | if ( $this->mSelectedTab == 'edit' && $section == 'new' ) { | |
570 | $this->mSelectedTab = 'addsection'; | |
571 | } | |
572 | } elseif ( $this->mTitle->isTalkPage() ) { | |
573 | $this->mSelectedTab = 'talk'; | |
574 | } else { | |
575 | $this->mSelectedTab = 'subject'; | |
576 | } | |
577 | } | |
578 | } | |
579 | if ( $extraclass ) { | |
580 | if ( $this->mSelectedTab == $tab ) { | |
581 | $s = 'class="selected ' . htmlspecialchars( $extraclass ) . '"'; | |
582 | } else { | |
583 | $s = 'class="' . htmlspecialchars( $extraclass ) . '"'; | |
584 | } | |
585 | } else { | |
586 | if ( $this->mSelectedTab == $tab ) { | |
587 | $s = 'class="selected"'; | |
588 | } else { | |
589 | $s = ''; | |
590 | } | |
591 | } | |
592 | return cbt_value( $s, array( 'nonview dynamic', 'title' ) ); | |
593 | } | |
594 | ||
595 | function subject_newclass() { | |
596 | $title = $this->getSubjectPage(); | |
597 | $class = $title->exists() ? '' : 'new'; | |
598 | return cbt_value( $class, 'dynamic' ); | |
599 | } | |
600 | ||
601 | function talk_newclass() { | |
602 | $title = $this->getTalkPage(); | |
603 | $class = $title->exists() ? '' : 'new'; | |
604 | return cbt_value( $class, 'dynamic' ); | |
605 | } | |
606 | ||
607 | function ca_variant( $code, $name, $index, $template ) { | |
608 | global $wgContLang; | |
609 | $selected = ($code == $wgContLang->getPreferredVariant()); | |
610 | $action = $this->getAction(); | |
611 | $actstr = ''; | |
612 | if( $action ) | |
613 | $actstr = 'action=' . $action . '&'; | |
614 | $s = strtr( $template, array( | |
615 | '$id' => htmlspecialchars( 'varlang-' . $index ), | |
616 | '$class' => $selected ? 'class="selected"' : '', | |
617 | '$text' => $name, | |
618 | '$href' => htmlspecialchars( $this->mTitle->getLocalUrl( $actstr . 'variant=' . $code ) ) | |
619 | )); | |
620 | return cbt_value( $s, 'dynamic' ); | |
621 | } | |
622 | ||
623 | function is_watching() { | |
624 | return cbt_value( (string)$this->mTitle->userIsWatching(), array( 'dynamic' ) ); | |
625 | } | |
626 | ||
627 | ||
628 | function personal_urls( $itemTemplate ) { | |
629 | global $wgShowIPinHeader, $wgContLang; | |
630 | ||
631 | # Split this function up into many small functions, to obtain the | |
632 | # best specificity in the dependencies of each one. The template below | |
633 | # has no dependencies, so its generation, and any static subfunctions, | |
634 | # can be optimised away. | |
635 | $etpl = cbt_escape( $itemTemplate ); | |
636 | $s = " | |
637 | {userpage {{$etpl}}} | |
638 | {mytalk {{$etpl}}} | |
639 | {preferences {{$etpl}}} | |
640 | {watchlist {{$etpl}}} | |
641 | {mycontris {{$etpl}}} | |
642 | {logout {{$etpl}}} | |
643 | "; | |
644 | ||
645 | if ( $wgShowIPinHeader ) { | |
646 | $s .= " | |
647 | {anonuserpage {{$etpl}}} | |
648 | {anontalk {{$etpl}}} | |
649 | {anonlogin {{$etpl}}} | |
650 | "; | |
651 | } else { | |
652 | $s .= "{login {{$etpl}}}\n"; | |
653 | } | |
654 | // No dependencies | |
655 | return cbt_value( $s, array(), true /*this is a template*/ ); | |
656 | } | |
657 | ||
658 | function userpage( $itemTemplate ) { | |
659 | global $wgUser; | |
660 | if ( $this->isLoggedIn() ) { | |
661 | $userPage = $this->getUserPageTitle(); | |
662 | $s = $this->makeTemplateLink( $itemTemplate, 'userpage', $userPage, $wgUser->getName() ); | |
663 | } else { | |
664 | $s = ''; | |
665 | } | |
666 | return cbt_value( $s, 'user' ); | |
667 | } | |
668 | ||
669 | function mytalk( $itemTemplate ) { | |
670 | global $wgUser; | |
671 | if ( $this->isLoggedIn() ) { | |
672 | $userPage = $this->getUserPageTitle(); | |
673 | $talkPage = $userPage->getTalkPage(); | |
674 | $s = $this->makeTemplateLink( $itemTemplate, 'mytalk', $talkPage, wfMsg('mytalk') ); | |
675 | } else { | |
676 | $s = ''; | |
677 | } | |
678 | return cbt_value( $s, 'user' ); | |
679 | } | |
680 | ||
681 | function preferences( $itemTemplate ) { | |
682 | if ( $this->isLoggedIn() ) { | |
683 | $s = $this->makeSpecialTemplateLink( $itemTemplate, 'preferences', | |
684 | 'Preferences', wfMsg( 'preferences' ) ); | |
685 | } else { | |
686 | $s = ''; | |
687 | } | |
688 | return cbt_value( $s, array( 'loggedin', 'lang' ) ); | |
689 | } | |
690 | ||
691 | function watchlist( $itemTemplate ) { | |
692 | if ( $this->isLoggedIn() ) { | |
693 | $s = $this->makeSpecialTemplateLink( $itemTemplate, 'watchlist', | |
694 | 'Watchlist', wfMsg( 'watchlist' ) ); | |
695 | } else { | |
696 | $s = ''; | |
697 | } | |
698 | return cbt_value( $s, array( 'loggedin', 'lang' ) ); | |
699 | } | |
700 | ||
701 | function mycontris( $itemTemplate ) { | |
702 | if ( $this->isLoggedIn() ) { | |
703 | global $wgUser; | |
704 | $s = $this->makeSpecialTemplateLink( $itemTemplate, 'mycontris', | |
705 | "Contributions/" . $wgUser->getTitleKey(), wfMsg('mycontris') ); | |
706 | } else { | |
707 | $s = ''; | |
708 | } | |
709 | return cbt_value( $s, 'user' ); | |
710 | } | |
711 | ||
712 | function logout( $itemTemplate ) { | |
713 | if ( $this->isLoggedIn() ) { | |
714 | $s = $this->makeSpecialTemplateLink( $itemTemplate, 'logout', | |
715 | 'Userlogout', wfMsg( 'userlogout' ), | |
716 | $this->mTitle->getNamespace() === NS_SPECIAL && $this->mTitle->getText() === 'Preferences' | |
717 | ? '' : "returnto=" . $this->mTitle->getPrefixedURL() ); | |
718 | } else { | |
719 | $s = ''; | |
720 | } | |
721 | return cbt_value( $s, 'loggedin dynamic' ); | |
722 | } | |
723 | ||
724 | function anonuserpage( $itemTemplate ) { | |
725 | if ( $this->isLoggedIn() ) { | |
726 | $s = ''; | |
727 | } else { | |
728 | global $wgUser; | |
729 | $userPage = $this->getUserPageTitle(); | |
730 | $s = $this->makeTemplateLink( $itemTemplate, 'userpage', $userPage, $wgUser->getName() ); | |
731 | } | |
732 | return cbt_value( $s, '!loggedin dynamic' ); | |
733 | } | |
734 | ||
735 | function anontalk( $itemTemplate ) { | |
736 | if ( $this->isLoggedIn() ) { | |
737 | $s = ''; | |
738 | } else { | |
739 | $userPage = $this->getUserPageTitle(); | |
740 | $talkPage = $userPage->getTalkPage(); | |
741 | $s = $this->makeTemplateLink( $itemTemplate, 'mytalk', $talkPage, wfMsg('anontalk') ); | |
742 | } | |
743 | return cbt_value( $s, '!loggedin dynamic' ); | |
744 | } | |
745 | ||
746 | function anonlogin( $itemTemplate ) { | |
747 | if ( $this->isLoggedIn() ) { | |
748 | $s = ''; | |
749 | } else { | |
750 | $s = $this->makeSpecialTemplateLink( $itemTemplate, 'anonlogin', 'Userlogin', | |
751 | wfMsg( 'userlogin' ), 'returnto=' . urlencode( $this->getThisPDBK() ) ); | |
752 | } | |
753 | return cbt_value( $s, '!loggedin dynamic' ); | |
754 | } | |
755 | ||
756 | function login( $itemTemplate ) { | |
757 | if ( $this->isLoggedIn() ) { | |
758 | $s = ''; | |
759 | } else { | |
760 | $s = $this->makeSpecialTemplateLink( $itemTemplate, 'login', 'Userlogin', | |
761 | wfMsg( 'userlogin' ), 'returnto=' . urlencode( $this->getThisPDBK() ) ); | |
762 | } | |
763 | return cbt_value( $s, '!loggedin dynamic' ); | |
764 | } | |
765 | ||
766 | function logopath() { return $GLOBALS['wgLogo']; } | |
767 | function mainpage() { return self::makeMainPageUrl(); } | |
768 | ||
769 | function sidebar( $startSection, $endSection, $innerTpl ) { | |
770 | $s = ''; | |
771 | $lines = explode( "\n", wfMsgForContent( 'sidebar' ) ); | |
772 | $firstSection = true; | |
773 | foreach ($lines as $line) { | |
774 | if (strpos($line, '*') !== 0) | |
775 | continue; | |
776 | if (strpos($line, '**') !== 0) { | |
777 | $bar = trim($line, '* '); | |
778 | $name = wfMsg( $bar ); | |
779 | if (wfEmptyMsg($bar, $name)) { | |
780 | $name = $bar; | |
781 | } | |
782 | if ( $firstSection ) { | |
783 | $firstSection = false; | |
784 | } else { | |
785 | $s .= $endSection; | |
786 | } | |
787 | $s .= strtr( $startSection, | |
788 | array( | |
789 | '$bar' => htmlspecialchars( $bar ), | |
790 | '$barname' => $name | |
791 | ) ); | |
792 | } else { | |
793 | if (strpos($line, '|') !== false) { // sanity check | |
794 | $line = explode( '|' , trim($line, '* '), 2 ); | |
795 | $link = wfMsgForContent( $line[0] ); | |
796 | if ($link == '-') | |
797 | continue; | |
798 | if (wfEmptyMsg($line[1], $text = wfMsg($line[1]))) | |
799 | $text = $line[1]; | |
800 | if (wfEmptyMsg($line[0], $link)) | |
801 | $link = $line[0]; | |
802 | $href = self::makeInternalOrExternalUrl( $link ); | |
803 | ||
804 | $s .= strtr( $innerTpl, | |
805 | array( | |
806 | '$text' => htmlspecialchars( $text ), | |
807 | '$href' => htmlspecialchars( $href ), | |
808 | '$id' => htmlspecialchars( 'n-' . strtr($line[1], ' ', '-') ), | |
809 | '$classactive' => '' | |
810 | ) ); | |
811 | } else { continue; } | |
812 | } | |
813 | } | |
814 | if ( !$firstSection ) { | |
815 | $s .= $endSection; | |
816 | } | |
817 | ||
818 | // Depends on user language only | |
819 | return cbt_value( $s, 'lang' ); | |
820 | } | |
821 | ||
822 | function searchaction() { | |
823 | // Static link | |
824 | return $this->getSearchLink(); | |
825 | } | |
826 | ||
827 | function search() { | |
828 | global $wgRequest; | |
829 | return cbt_value( trim( $this->getSearch() ), 'special dynamic' ); | |
830 | } | |
831 | ||
832 | function notspecialpage() { | |
833 | return cbt_value( $this->mTitle->getNamespace() != NS_SPECIAL, 'special' ); | |
834 | } | |
835 | ||
836 | function nav_whatlinkshere() { | |
837 | return cbt_value( $this->makeSpecialParamUrl('Whatlinkshere' ), array(), true ); | |
838 | } | |
839 | ||
840 | function article_exists() { | |
841 | return cbt_value( (string)($this->mTitle->getArticleId() !== 0), 'title' ); | |
842 | } | |
843 | ||
844 | function nav_recentchangeslinked() { | |
845 | return cbt_value( $this->makeSpecialParamUrl('Recentchangeslinked' ), array(), true ); | |
846 | } | |
847 | ||
848 | function feeds( $itemTemplate = '' ) { | |
849 | if ( !$this->mOut->isSyndicated() ) { | |
850 | $feeds = ''; | |
851 | } elseif ( $itemTemplate == '' ) { | |
852 | // boolean only required | |
853 | $feeds = 'true'; | |
854 | } else { | |
855 | $feeds = ''; | |
856 | global $wgFeedClasses, $wgRequest; | |
857 | foreach( $wgFeedClasses as $format => $class ) { | |
858 | $feeds .= strtr( $itemTemplate, | |
859 | array( | |
860 | '$key' => htmlspecialchars( $format ), | |
861 | '$text' => $format, | |
862 | '$href' => $wgRequest->appendQuery( "feed=$format" ) | |
863 | ) ); | |
864 | } | |
865 | } | |
866 | return cbt_value( $feeds, 'special dynamic' ); | |
867 | } | |
868 | ||
869 | function is_userpage() { | |
870 | list( $id, $ip ) = $this->getUserPageIdIp(); | |
871 | return cbt_value( (string)($id || $ip), 'title' ); | |
872 | } | |
873 | ||
874 | function is_ns_mediawiki() { | |
875 | return cbt_value( (string)$this->mTitle->getNamespace() == NS_MEDIAWIKI, 'title' ); | |
876 | } | |
877 | ||
878 | function is_loggedin() { | |
879 | global $wgUser; | |
880 | return cbt_value( (string)($wgUser->isLoggedIn()), 'loggedin' ); | |
881 | } | |
882 | ||
883 | function nav_contributions() { | |
884 | $url = $this->makeSpecialParamUrl( 'Contributions', '', '{title_userurl}' ); | |
885 | return cbt_value( $url, array(), true ); | |
886 | } | |
887 | ||
888 | function is_allowed( $right ) { | |
889 | global $wgUser; | |
890 | return cbt_value( (string)$wgUser->isAllowed( $right ), 'user' ); | |
891 | } | |
892 | ||
893 | function nav_blockip() { | |
894 | $url = $this->makeSpecialParamUrl( 'Blockip', '', '{title_userurl}' ); | |
895 | return cbt_value( $url, array(), true ); | |
896 | } | |
897 | ||
898 | function nav_emailuser() { | |
899 | global $wgEnableEmail, $wgEnableUserEmail, $wgUser; | |
900 | if ( !$wgEnableEmail || !$wgEnableUserEmail ) return ''; | |
901 | ||
902 | $url = $this->makeSpecialParamUrl( 'Emailuser', '', '{title_userurl}' ); | |
903 | return cbt_value( $url, array(), true ); | |
904 | } | |
905 | ||
906 | function nav_upload() { | |
907 | global $wgEnableUploads, $wgUploadNavigationUrl; | |
908 | if ( !$wgEnableUploads ) { | |
909 | return ''; | |
910 | } elseif ( $wgUploadNavigationUrl ) { | |
911 | return $wgUploadNavigationUrl; | |
912 | } else { | |
913 | return self::makeSpecialUrl('Upload'); | |
914 | } | |
915 | } | |
916 | ||
917 | function nav_specialpages() { | |
918 | return self::makeSpecialUrl('Specialpages'); | |
919 | } | |
920 | ||
921 | function nav_print() { | |
922 | global $wgRequest, $wgArticle; | |
923 | $action = $this->getAction(); | |
924 | $url = ''; | |
925 | if( $this->mTitle->getNamespace() !== NS_SPECIAL | |
926 | && ($action == '' || $action == 'view' || $action == 'purge' ) ) | |
927 | { | |
928 | $revid = $wgArticle->getLatest(); | |
929 | if ( $revid != 0 ) { | |
930 | $url = $wgRequest->appendQuery( 'printable=yes' ); | |
931 | } | |
932 | } | |
933 | return cbt_value( $url, array( 'nonview dynamic', 'title' ) ); | |
934 | } | |
935 | ||
936 | function nav_permalink() { | |
937 | $url = (string)$this->getPermalink(); | |
938 | return cbt_value( $url, 'dynamic' ); | |
939 | } | |
940 | ||
941 | function nav_trackbacklink() { | |
942 | global $wgUseTrackbacks; | |
943 | if ( !$wgUseTrackbacks ) return ''; | |
944 | ||
945 | return cbt_value( $this->mTitle->trackbackURL(), 'title' ); | |
946 | } | |
947 | ||
948 | function is_permalink() { | |
949 | return cbt_value( (string)($this->getPermalink() === false), 'nonview dynamic' ); | |
950 | } | |
951 | ||
952 | function toolboxend() { | |
953 | // This is where the MonoBookTemplateToolboxEnd hook went in the old skin | |
954 | return ''; | |
955 | } | |
956 | ||
957 | function language_urls( $outer, $inner ) { | |
958 | global $wgHideInterlanguageLinks, $wgOut, $wgContLang; | |
959 | if ( $wgHideInterlanguageLinks ) return ''; | |
960 | ||
961 | $links = $wgOut->getLanguageLinks(); | |
962 | $s = ''; | |
963 | if ( count( $links ) ) { | |
964 | foreach( $links as $l ) { | |
965 | $tmp = explode( ':', $l, 2 ); | |
966 | $nt = Title::newFromText( $l ); | |
967 | $s .= strtr( $inner, | |
968 | array( | |
969 | '$class' => htmlspecialchars( 'interwiki-' . $tmp[0] ), | |
970 | '$href' => htmlspecialchars( $nt->getFullURL() ), | |
971 | '$text' => ($wgContLang->getLanguageName( $nt->getInterwiki() ) != ''? | |
972 | $wgContLang->getLanguageName( $nt->getInterwiki() ) : $l ), | |
973 | ) | |
974 | ); | |
975 | } | |
976 | $s = str_replace( '$body', $s, $outer ); | |
977 | } | |
978 | return cbt_value( $s, 'dynamic' ); | |
979 | } | |
980 | ||
981 | function poweredbyico() { return $this->getPoweredBy(); } | |
982 | function copyrightico() { return $this->getCopyrightIcon(); } | |
983 | ||
984 | function lastmod() { | |
985 | global $wgMaxCredits; | |
986 | if ( $wgMaxCredits ) return ''; | |
987 | ||
988 | if ( !isset( $this->mLastmod ) ) { | |
989 | if ( $this->isCurrentArticleView() ) { | |
990 | $this->mLastmod = $this->lastModified(); | |
991 | } else { | |
992 | $this->mLastmod = ''; | |
993 | } | |
994 | } | |
995 | return cbt_value( $this->mLastmod, 'dynamic' ); | |
996 | } | |
997 | ||
998 | function viewcount() { | |
999 | global $wgDisableCounters; | |
1000 | if ( $wgDisableCounters ) return ''; | |
1001 | ||
1002 | global $wgLang, $wgArticle; | |
1003 | if ( is_object( $wgArticle ) ) { | |
1004 | $viewcount = $wgLang->formatNum( $wgArticle->getCount() ); | |
1005 | if ( $viewcount ) { | |
1006 | $viewcount = wfMsg( "viewcount", $viewcount ); | |
1007 | } else { | |
1008 | $viewcount = ''; | |
1009 | } | |
1010 | } else { | |
1011 | $viewcount = ''; | |
1012 | } | |
1013 | return cbt_value( $viewcount, 'dynamic' ); | |
1014 | } | |
1015 | ||
1016 | function numberofwatchingusers() { | |
1017 | global $wgPageShowWatchingUsers; | |
1018 | if ( !$wgPageShowWatchingUsers ) return ''; | |
1019 | ||
1020 | $dbr = wfGetDB( DB_SLAVE ); | |
1021 | extract( $dbr->tableNames( 'watchlist' ) ); | |
1022 | $sql = "SELECT COUNT(*) AS n FROM $watchlist | |
1023 | WHERE wl_title='" . $dbr->strencode($this->mTitle->getDBkey()) . | |
1024 | "' AND wl_namespace=" . $this->mTitle->getNamespace() ; | |
1025 | $res = $dbr->query( $sql, 'SkinTemplate::outputPage'); | |
1026 | $row = $dbr->fetchObject( $res ); | |
1027 | $num = $row->n; | |
1028 | if ($num > 0) { | |
1029 | $s = wfMsg('number_of_watching_users_pageview', $num); | |
1030 | } else { | |
1031 | $s = ''; | |
1032 | } | |
1033 | return cbt_value( $s, 'dynamic' ); | |
1034 | } | |
1035 | ||
1036 | function credits() { | |
1037 | global $wgMaxCredits; | |
1038 | if ( !$wgMaxCredits ) return ''; | |
1039 | ||
1040 | if ( $this->isCurrentArticleView() ) { | |
1041 | require_once("Credits.php"); | |
1042 | global $wgArticle, $wgShowCreditsIfMax; | |
1043 | $credits = getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax); | |
1044 | } else { | |
1045 | $credits = ''; | |
1046 | } | |
1047 | return cbt_value( $credits, 'view dynamic' ); | |
1048 | } | |
1049 | ||
1050 | function normalcopyright() { | |
1051 | return $this->getCopyright( 'normal' ); | |
1052 | } | |
1053 | ||
1054 | function historycopyright() { | |
1055 | return $this->getCopyright( 'history' ); | |
1056 | } | |
1057 | ||
1058 | function is_currentview() { | |
1059 | global $wgRequest; | |
1060 | return cbt_value( (string)$this->isCurrentArticleView(), 'view' ); | |
1061 | } | |
1062 | ||
1063 | function usehistorycopyright() { | |
1064 | global $wgRequest; | |
1065 | if ( wfMsgForContent( 'history_copyright' ) == '-' ) return ''; | |
1066 | ||
1067 | $oldid = $this->getOldId(); | |
1068 | $diff = $this->getDiff(); | |
1069 | $use = (string)(!is_null( $oldid ) && is_null( $diff )); | |
1070 | return cbt_value( $use, 'nonview dynamic' ); | |
1071 | } | |
1072 | ||
1073 | function privacy() { | |
1074 | return cbt_value( $this->privacyLink(), 'lang' ); | |
1075 | } | |
1076 | function about() { | |
1077 | return cbt_value( $this->aboutLink(), 'lang' ); | |
1078 | } | |
1079 | function disclaimer() { | |
1080 | return cbt_value( $this->disclaimerLink(), 'lang' ); | |
1081 | } | |
1082 | function tagline() { | |
1083 | # A reference to this tag existed in the old MonoBook.php, but the | |
1084 | # template data wasn't set anywhere | |
1085 | return ''; | |
1086 | } | |
1087 | function reporttime() { | |
1088 | return cbt_value( $this->mOut->reportTime(), 'dynamic' ); | |
1089 | } | |
1090 | ||
1091 | function msg( $name ) { | |
1092 | return cbt_value( wfMsg( $name ), 'lang' ); | |
1093 | } | |
1094 | ||
1095 | function fallbackmsg( $name, $fallback ) { | |
1096 | $text = wfMsg( $name ); | |
1097 | if ( wfEmptyMsg( $name, $text ) ) { | |
1098 | $text = $fallback; | |
1099 | } | |
1100 | return cbt_value( $text, 'lang' ); | |
1101 | } | |
1102 | ||
1103 | /****************************************************** | |
1104 | * Utility functions * | |
1105 | ******************************************************/ | |
1106 | ||
1107 | /** Return true if this request is a valid, secure CSS preview */ | |
1108 | function isCssPreview() { | |
1109 | if ( !isset( $this->mCssPreview ) ) { | |
1110 | global $wgRequest, $wgAllowUserCss, $wgUser; | |
1111 | $this->mCssPreview = | |
1112 | $wgAllowUserCss && | |
1113 | $wgUser->isLoggedIn() && | |
1114 | $this->mTitle->isCssSubpage() && | |
1115 | $this->userCanPreview( $this->getAction() ); | |
1116 | } | |
1117 | return $this->mCssPreview; | |
1118 | } | |
1119 | ||
1120 | /** Return true if this request is a valid, secure JS preview */ | |
1121 | function isJsPreview() { | |
1122 | if ( !isset( $this->mJsPreview ) ) { | |
1123 | global $wgRequest, $wgAllowUserJs, $wgUser; | |
1124 | $this->mJsPreview = | |
1125 | $wgAllowUserJs && | |
1126 | $wgUser->isLoggedIn() && | |
1127 | $this->mTitle->isJsSubpage() && | |
1128 | $this->userCanPreview( $this->getAction() ); | |
1129 | } | |
1130 | return $this->mJsPreview; | |
1131 | } | |
1132 | ||
1133 | /** Get the title of the $wgUser's user page */ | |
1134 | function getUserPageTitle() { | |
1135 | if ( !isset( $this->mUserPageTitle ) ) { | |
1136 | global $wgUser; | |
1137 | $this->mUserPageTitle = $wgUser->getUserPage(); | |
1138 | } | |
1139 | return $this->mUserPageTitle; | |
1140 | } | |
1141 | ||
1142 | /** Get the text of the user page title */ | |
1143 | function getUserPageText() { | |
1144 | if ( !isset( $this->mUserPageText ) ) { | |
1145 | $userPage = $this->getUserPageTitle(); | |
1146 | $this->mUserPageText = $userPage->getPrefixedText(); | |
1147 | } | |
1148 | return $this->mUserPageText; | |
1149 | } | |
1150 | ||
1151 | /** Make an HTML element for a stylesheet link */ | |
1152 | function makeStylesheetLink( $url ) { | |
1153 | return '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars( $url ) . "\"/>"; | |
1154 | } | |
1155 | ||
1156 | /** Make an XHTML element for inline CSS */ | |
1157 | function makeStylesheetCdata( $style ) { | |
1158 | return "<style type=\"text/css\"> /*<![CDATA[*/ {$style} /*]]>*/ </style>"; | |
1159 | } | |
1160 | ||
1161 | /** Get the edit URL for this page */ | |
1162 | function getEditUrl() { | |
1163 | if ( !isset( $this->mEditUrl ) ) { | |
1164 | $this->mEditUrl = $this->mTitle->getLocalUrl( $this->editUrlOptions() ); | |
1165 | } | |
1166 | return $this->mEditUrl; | |
1167 | } | |
1168 | ||
1169 | /** Get the prefixed DB key for this page */ | |
1170 | function getThisPDBK() { | |
1171 | if ( !isset( $this->mThisPDBK ) ) { | |
1172 | $this->mThisPDBK = $this->mTitle->getPrefixedDbKey(); | |
1173 | } | |
1174 | return $this->mThisPDBK; | |
1175 | } | |
1176 | ||
1177 | function getThisTitleUrlForm() { | |
1178 | if ( !isset( $this->mThisTitleUrlForm ) ) { | |
1179 | $this->mThisTitleUrlForm = $this->mTitle->getPrefixedURL(); | |
1180 | } | |
1181 | return $this->mThisTitleUrlForm; | |
1182 | } | |
1183 | ||
1184 | /** | |
1185 | * If the current page is a user page, get the user's ID and IP. Otherwise return array(0,false) | |
1186 | */ | |
1187 | function getUserPageIdIp() { | |
1188 | if ( !isset( $this->mUserPageId ) ) { | |
1189 | if( $this->mTitle->getNamespace() == NS_USER || $this->mTitle->getNamespace() == NS_USER_TALK ) { | |
1190 | $this->mUserPageId = User::idFromName($this->mTitle->getText()); | |
1191 | $this->mUserPageIp = User::isIP($this->mTitle->getText()); | |
1192 | } else { | |
1193 | $this->mUserPageId = 0; | |
1194 | $this->mUserPageIp = false; | |
1195 | } | |
1196 | } | |
1197 | return array( $this->mUserPageId, $this->mUserPageIp ); | |
1198 | } | |
1199 | ||
1200 | /** | |
1201 | * Returns a permalink URL, or false if the current page is already a | |
1202 | * permalink, or blank if a permalink shouldn't be displayed | |
1203 | */ | |
1204 | function getPermalink() { | |
1205 | if ( !isset( $this->mPermalink ) ) { | |
1206 | global $wgRequest, $wgArticle; | |
1207 | $action = $this->getAction(); | |
1208 | $oldid = $this->getOldId(); | |
1209 | $url = ''; | |
1210 | if( $this->mTitle->getNamespace() !== NS_SPECIAL | |
1211 | && $this->mTitle->getArticleId() != 0 | |
1212 | && ($action == '' || $action == 'view' || $action == 'purge' ) ) | |
1213 | { | |
1214 | if ( !$oldid ) { | |
1215 | $revid = $wgArticle->getLatest(); | |
1216 | $url = $this->mTitle->getLocalURL( "oldid=$revid" ); | |
1217 | } else { | |
1218 | $url = false; | |
1219 | } | |
1220 | } else { | |
1221 | $url = ''; | |
1222 | } | |
1223 | } | |
1224 | return $url; | |
1225 | } | |
1226 | ||
1227 | /** | |
1228 | * Returns true if the current page is an article, not a special page, | |
1229 | * and we are viewing a revision, not a diff | |
1230 | */ | |
1231 | function isArticleView() { | |
1232 | global $wgOut, $wgArticle, $wgRequest; | |
1233 | if ( !isset( $this->mIsArticleView ) ) { | |
1234 | $oldid = $this->getOldId(); | |
1235 | $diff = $this->getDiff(); | |
1236 | $this->mIsArticleView = $wgOut->isArticle() and | |
1237 | (!is_null( $oldid ) or is_null( $diff )) and 0 != $wgArticle->getID(); | |
1238 | } | |
1239 | return $this->mIsArticleView; | |
1240 | } | |
1241 | ||
1242 | function isCurrentArticleView() { | |
1243 | if ( !isset( $this->mIsCurrentArticleView ) ) { | |
1244 | global $wgOut, $wgArticle, $wgRequest; | |
1245 | $oldid = $this->getOldId(); | |
1246 | $this->mIsCurrentArticleView = $wgOut->isArticle() && is_null( $oldid ) && 0 != $wgArticle->getID(); | |
1247 | } | |
1248 | return $this->mIsCurrentArticleView; | |
1249 | } | |
1250 | ||
1251 | ||
1252 | /** | |
1253 | * Return true if the current page is editable; if edit section on right | |
1254 | * click should be enabled. | |
1255 | */ | |
1256 | function isEditable() { | |
1257 | global $wgRequest; | |
1258 | $action = $this->getAction(); | |
1259 | return ($this->mTitle->getNamespace() != NS_SPECIAL and !($action == 'edit' or $action == 'submit')); | |
1260 | } | |
1261 | ||
1262 | /** Return true if the user is logged in */ | |
1263 | function isLoggedIn() { | |
1264 | global $wgUser; | |
1265 | return $wgUser->isLoggedIn(); | |
1266 | } | |
1267 | ||
1268 | /** Get the local URL of the current page */ | |
1269 | function getPageUrl() { | |
1270 | if ( !isset( $this->mPageUrl ) ) { | |
1271 | $this->mPageUrl = $this->mTitle->getLocalURL(); | |
1272 | } | |
1273 | return $this->mPageUrl; | |
1274 | } | |
1275 | ||
1276 | /** Make a link to a title using a template */ | |
1277 | function makeTemplateLink( $template, $key, $title, $text ) { | |
1278 | $url = $title->getLocalUrl(); | |
1279 | return strtr( $template, | |
1280 | array( | |
1281 | '$key' => $key, | |
1282 | '$classactive' => ($url == $this->getPageUrl()) ? 'class="active"' : '', | |
1283 | '$class' => $title->getArticleID() == 0 ? 'class="new"' : '', | |
1284 | '$href' => htmlspecialchars( $url ), | |
1285 | '$text' => $text | |
1286 | ) ); | |
1287 | } | |
1288 | ||
1289 | /** Make a link to a URL using a template */ | |
1290 | function makeTemplateLinkUrl( $template, $key, $url, $text ) { | |
1291 | return strtr( $template, | |
1292 | array( | |
1293 | '$key' => $key, | |
1294 | '$classactive' => ($url == $this->getPageUrl()) ? 'class="active"' : '', | |
1295 | '$class' => '', | |
1296 | '$href' => htmlspecialchars( $url ), | |
1297 | '$text' => $text | |
1298 | ) ); | |
1299 | } | |
1300 | ||
1301 | /** Make a link to a special page using a template */ | |
1302 | function makeSpecialTemplateLink( $template, $key, $specialName, $text, $query = '' ) { | |
1303 | $url = self::makeSpecialUrl( $specialName, $query ); | |
1304 | // Ignore the query when comparing | |
1305 | $active = ($this->mTitle->getNamespace() == NS_SPECIAL && $this->mTitle->getDBkey() == $specialName); | |
1306 | return strtr( $template, | |
1307 | array( | |
1308 | '$key' => $key, | |
1309 | '$classactive' => $active ? 'class="active"' : '', | |
1310 | '$class' => '', | |
1311 | '$href' => htmlspecialchars( $url ), | |
1312 | '$text' => $text | |
1313 | ) ); | |
1314 | } | |
1315 | ||
1316 | function loadRequestValues() { | |
1317 | global $wgRequest; | |
1318 | $this->mAction = $wgRequest->getText( 'action' ); | |
1319 | $this->mOldId = $wgRequest->getVal( 'oldid' ); | |
1320 | $this->mDiff = $wgRequest->getVal( 'diff' ); | |
1321 | $this->mSection = $wgRequest->getVal( 'section' ); | |
1322 | $this->mSearch = $wgRequest->getVal( 'search' ); | |
1323 | $this->mRequestValuesLoaded = true; | |
1324 | } | |
1325 | ||
1326 | ||
1327 | ||
1328 | /** Get the action parameter of the request */ | |
1329 | function getAction() { | |
1330 | if ( !isset( $this->mRequestValuesLoaded ) ) { | |
1331 | $this->loadRequestValues(); | |
1332 | } | |
1333 | return $this->mAction; | |
1334 | } | |
1335 | ||
1336 | /** Get the oldid parameter */ | |
1337 | function getOldId() { | |
1338 | if ( !isset( $this->mRequestValuesLoaded ) ) { | |
1339 | $this->loadRequestValues(); | |
1340 | } | |
1341 | return $this->mOldId; | |
1342 | } | |
1343 | ||
1344 | /** Get the diff parameter */ | |
1345 | function getDiff() { | |
1346 | if ( !isset( $this->mRequestValuesLoaded ) ) { | |
1347 | $this->loadRequestValues(); | |
1348 | } | |
1349 | return $this->mDiff; | |
1350 | } | |
1351 | ||
1352 | function getSection() { | |
1353 | if ( !isset( $this->mRequestValuesLoaded ) ) { | |
1354 | $this->loadRequestValues(); | |
1355 | } | |
1356 | return $this->mSection; | |
1357 | } | |
1358 | ||
1359 | function getSearch() { | |
1360 | if ( !isset( $this->mRequestValuesLoaded ) ) { | |
1361 | $this->loadRequestValues(); | |
1362 | } | |
1363 | return $this->mSearch; | |
1364 | } | |
1365 | ||
1366 | /** Make a special page URL of the form [[Special:Somepage/{title_urlform}]] */ | |
1367 | function makeSpecialParamUrl( $name, $query = '', $param = '{title_urlform}' ) { | |
1368 | // Abuse makeTitle's lax validity checking to slip a control character into the URL | |
1369 | $title = Title::makeTitle( NS_SPECIAL, "$name/\x1a" ); | |
1370 | $url = cbt_escape( $title->getLocalURL( $query ) ); | |
1371 | // Now replace it with the parameter | |
1372 | return str_replace( '%1A', $param, $url ); | |
1373 | } | |
1374 | ||
1375 | function getSubjectPage() { | |
1376 | if ( !isset( $this->mSubjectPage ) ) { | |
1377 | $this->mSubjectPage = $this->mTitle->getSubjectPage(); | |
1378 | } | |
1379 | return $this->mSubjectPage; | |
1380 | } | |
1381 | ||
1382 | function getTalkPage() { | |
1383 | if ( !isset( $this->mTalkPage ) ) { | |
1384 | $this->mTalkPage = $this->mTitle->getTalkPage(); | |
1385 | } | |
1386 | return $this->mTalkPage; | |
1387 | } | |
1388 | } | |
1389 |