Ahh, so that's what that does
[lhc/web/wiklou.git] / includes / Skin.php
1 <?php
2
3 # This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
4 if( defined( "MEDIAWIKI" ) ) {
5
6 # See skin.doc
7
8 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
9 require_once( 'Image.php' );
10
11 # These are the INTERNAL names, which get mapped
12 # directly to class names. For display purposes, the
13 # Language class has internationalized names
14 #
15 /* private */ $wgValidSkinNames = array(
16 'standard' => 'Standard',
17 'nostalgia' => 'Nostalgia',
18 'cologneblue' => 'CologneBlue'
19 );
20 if( $wgUsePHPTal ) {
21 #$wgValidSkinNames[] = 'PHPTal';
22 #$wgValidSkinNames['davinci'] = 'DaVinci';
23 #$wgValidSkinNames['mono'] = 'Mono';
24 $wgValidSkinNames['monobook'] = 'MonoBook';
25 $wgValidSkinNames['myskin'] = 'MySkin';
26 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
27 }
28
29 require_once( 'RecentChange.php' );
30
31 class RCCacheEntry extends RecentChange
32 {
33 var $secureName, $link;
34 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
35 var $userlink, $timestamp, $watched;
36
37 function newFromParent( $rc )
38 {
39 $rc2 = new RCCacheEntry;
40 $rc2->mAttribs = $rc->mAttribs;
41 $rc2->mExtra = $rc->mExtra;
42 return $rc2;
43 }
44 } ;
45
46 class Skin {
47
48 /* private */ var $lastdate, $lastline;
49 var $linktrail ; # linktrail regexp
50 var $rc_cache ; # Cache for Enhanced Recent Changes
51 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
52 var $rcMoveIndex;
53 var $postParseLinkColour = true;
54
55 function Skin()
56 {
57 $this->linktrail = wfMsg('linktrail');
58 }
59
60 function getSkinNames()
61 {
62 global $wgValidSkinNames;
63 return $wgValidSkinNames;
64 }
65
66 function getStylesheet()
67 {
68 return 'wikistandard.css';
69 }
70 function getSkinName() {
71 return "standard";
72 }
73
74 # Get/set accessor for delayed link colouring
75 function postParseLinkColour( $setting = NULL ) {
76 return wfSetVar( $this->postParseLinkColour, $setting );
77 }
78
79 function qbSetting()
80 {
81 global $wgOut, $wgUser;
82
83 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
84 $q = $wgUser->getOption( 'quickbar' );
85 if ( '' == $q ) { $q = 0; }
86 return $q;
87 }
88
89 function initPage( &$out )
90 {
91 $fname = 'Skin::initPage';
92 wfProfileIn( $fname );
93
94 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
95
96 $this->addMetadataLinks($out);
97
98 wfProfileOut( $fname );
99 }
100
101 function addMetadataLinks( &$out ) {
102 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
103 global $wgRightsPage, $wgRightsUrl;
104
105 if( $out->isArticleRelated() ) {
106 # note: buggy CC software only reads first "meta" link
107 if( $wgEnableCreativeCommonsRdf ) {
108 $out->addMetadataLink( array(
109 'title' => 'Creative Commons',
110 'type' => 'application/rdf+xml',
111 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
112 }
113 if( $wgEnableDublinCoreRdf ) {
114 $out->addMetadataLink( array(
115 'title' => 'Dublin Core',
116 'type' => 'application/rdf+xml',
117 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
118 }
119 }
120 $copyright = '';
121 if( $wgRightsPage ) {
122 $copy = Title::newFromText( $wgRightsPage );
123 if( $copy ) {
124 $copyright = $copy->getLocalURL();
125 }
126 }
127 if( !$copyright && $wgRightsUrl ) {
128 $copyright = $wgRightsUrl;
129 }
130 if( $copyright ) {
131 $out->addLink( array(
132 'rel' => 'copyright',
133 'href' => $copyright ) );
134 }
135 }
136
137 function outputPage( &$out ) {
138 global $wgDebugComments;
139
140 wfProfileIn( 'Skin::outputPage' );
141 $this->initPage( $out );
142 $out->out( $out->headElement() );
143
144 $out->out( "\n<body" );
145 $ops = $this->getBodyOptions();
146 foreach ( $ops as $name => $val ) {
147 $out->out( " $name='$val'" );
148 }
149 $out->out( ">\n" );
150 if ( $wgDebugComments ) {
151 $out->out( "<!-- Wiki debugging output:\n" .
152 $out->mDebugtext . "-->\n" );
153 }
154 $out->out( $this->beforeContent() );
155
156 $out->out( $out->mBodytext . "\n" );
157
158 $out->out( $this->afterContent() );
159
160 wfProfileClose();
161 $out->out( $out->reportTime() );
162
163 $out->out( "\n</body></html>" );
164 }
165
166 function getHeadScripts() {
167 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
168 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
169 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
170 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
171 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
172 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
173 }
174 return $r;
175 }
176
177 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
178 function getUserStylesheet() {
179 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
180 $sheet = $this->getStylesheet();
181 $action = $wgRequest->getText('action');
182 $s = "@import \"$wgStylePath/$sheet\";\n";
183 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
184 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
185 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
186 $s .= $wgRequest->getText('wpTextbox1');
187 } else {
188 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
189 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
190 }
191 }
192 $s .= $this->doGetUserStyles();
193 return $s."\n";
194 }
195 # placeholder, returns generated js in monobook
196 function getUserJs() {
197 return;
198 }
199
200 function getUserStyles()
201 {
202 global $wgOut, $wgStylePath, $wgLang;
203 $s = "<style type='text/css'>\n";
204 $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
205 $s .= $this->getUserStylesheet();
206 $s .= "/* */\n";
207 $s .= "</style>\n";
208 return $s;
209 }
210
211 function doGetUserStyles()
212 {
213 global $wgUser, $wgLang;
214
215 $csspage = $wgLang->getNsText( NS_MEDIAWIKI ) . ":" . $this->getSkinName() . ".css";
216 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
217
218 if ( 1 == $wgUser->getOption( 'underline' ) ) {
219 # Don't override browser settings
220 } else {
221 # CHECK MERGE @@@
222 # Force no underline
223 $s .= "a { text-decoration: none; }\n";
224 }
225 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
226 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
227 }
228 if ( 1 == $wgUser->getOption( 'justify' ) ) {
229 $s .= "#article { text-align: justify; }\n";
230 }
231 return $s;
232 }
233
234 function getBodyOptions()
235 {
236 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
237
238 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
239
240 if ( 0 != $wgTitle->getNamespace() ) {
241 $a = array( 'bgcolor' => '#ffffec' );
242 }
243 else $a = array( 'bgcolor' => '#FFFFFF' );
244 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
245 (!$wgTitle->isProtected() || $wgUser->isSysop()) ) {
246 $t = wfMsg( 'editthispage' );
247 $oid = $red = '';
248 if ( !empty($redirect) ) {
249 $red = "&redirect={$redirect}";
250 }
251 if ( !empty($oldid) && ! isset( $diff ) ) {
252 $oid = "&oldid={$oldid}";
253 }
254 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
255 $s = 'document.location = "' .$s .'";';
256 $a += array ('ondblclick' => $s);
257
258 }
259 $a['onload'] = $wgOut->getOnloadHandler();
260 return $a;
261 }
262
263 function getExternalLinkAttributes( $link, $text, $class='' )
264 {
265 global $wgUser, $wgOut, $wgLang;
266
267 $link = urldecode( $link );
268 $link = $wgLang->checkTitleEncoding( $link );
269 $link = str_replace( '_', ' ', $link );
270 $link = wfEscapeHTML( $link );
271
272 $r = ($class != '') ? " class='$class'" : " class='external'";
273
274 if ( 1 == $wgUser->getOption( 'hover' ) ) {
275 $r .= " title=\"{$link}\"";
276 }
277 return $r;
278 }
279
280 function getInternalLinkAttributes( $link, $text, $broken = false )
281 {
282 global $wgUser, $wgOut;
283
284 $link = urldecode( $link );
285 $link = str_replace( '_', ' ', $link );
286 $link = wfEscapeHTML( $link );
287
288 if ( $broken == 'stub' ) {
289 $r = ' class="stub"';
290 } else if ( $broken == 'yes' ) {
291 $r = ' class="new"';
292 } else {
293 $r = '';
294 }
295
296 if ( 1 == $wgUser->getOption( 'hover' ) ) {
297 $r .= " title=\"{$link}\"";
298 }
299 return $r;
300 }
301
302 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
303 {
304 global $wgUser, $wgOut;
305
306 if ( $broken == 'stub' ) {
307 $r = ' class="stub"';
308 } else if ( $broken == 'yes' ) {
309 $r = ' class="new"';
310 } else {
311 $r = '';
312 }
313
314 if ( 1 == $wgUser->getOption( 'hover' ) ) {
315 $r .= ' title ="' . $nt->getEscapedText() . '"';
316 }
317 return $r;
318 }
319
320 function getLogo()
321 {
322 global $wgLogo;
323 return $wgLogo;
324 }
325
326 # This will be called immediately after the <body> tag. Split into
327 # two functions to make it easier to subclass.
328 #
329 function beforeContent()
330 {
331 global $wgUser, $wgOut;
332
333 return $this->doBeforeContent();
334 }
335
336 function doBeforeContent()
337 {
338 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
339 $fname = 'Skin::doBeforeContent';
340 wfProfileIn( $fname );
341
342 $s = '';
343 $qb = $this->qbSetting();
344
345 if( $langlinks = $this->otherLanguages() ) {
346 $rows = 2;
347 $borderhack = '';
348 } else {
349 $rows = 1;
350 $langlinks = false;
351 $borderhack = 'class="top"';
352 }
353
354 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
355 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
356
357 $shove = ($qb != 0);
358 $left = ($qb == 1 || $qb == 3);
359 if($wgLang->isRTL()) $left = !$left;
360
361 if ( !$shove ) {
362 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
363 $this->logoText() . '</td>';
364 } elseif( $left ) {
365 $s .= $this->getQuickbarCompensator( $rows );
366 }
367 $l = $wgLang->isRTL() ? 'right' : 'left';
368 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
369
370 $s .= $this->topLinks() ;
371 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
372
373 $r = $wgLang->isRTL() ? "left" : "right";
374 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
375 $s .= $this->nameAndLogin();
376 $s .= "\n<br />" . $this->searchForm() . "</td>";
377
378 if ( $langlinks ) {
379 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
380 }
381
382 if ( $shove && !$left ) { # Right
383 $s .= $this->getQuickbarCompensator( $rows );
384 }
385 $s .= "</tr>\n</table>\n</div>\n";
386 $s .= "\n<div id='article'>\n";
387
388 if( $wgSiteNotice ) {
389 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
390 }
391 $s .= $this->pageTitle();
392 $s .= $this->pageSubtitle() ;
393 $s .= $this->getCategories();
394 wfProfileOut( $fname );
395 return $s;
396 }
397
398 function getCategoryLinks () {
399 global $wgOut, $wgTitle, $wgUser, $wgParser;
400 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
401
402 if( !$wgUseCategoryMagic ) return '' ;
403 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
404
405 # Taken out so that they will be displayed in previews -- TS
406 #if( !$wgOut->isArticle() ) return '';
407
408 $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
409 $s = $this->makeKnownLink( 'Special:Categories',
410 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
411 . ': ' . $t;
412
413 if($wgUseCategoryBrowser) {
414 $s .= '<br/><hr/>';
415 $catstack = array();
416 $s.= $wgTitle->getAllParentCategories($catstack);
417 }
418
419 return $s;
420 }
421
422 function getCategories() {
423 $catlinks=$this->getCategoryLinks();
424 if(!empty($catlinks)) {
425 return "<p class='catlinks'>{$catlinks}</p>";
426 }
427 }
428
429 function getQuickbarCompensator( $rows = 1 )
430 {
431 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
432 }
433
434 # This gets called immediately before the </body> tag.
435 #
436 function afterContent()
437 {
438 global $wgUser, $wgOut, $wgServer;
439 global $wgTitle, $wgLang;
440
441 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
442 return $printfooter . $this->doAfterContent();
443 }
444
445 function printSource() {
446 global $wgTitle;
447 $url = htmlspecialchars( $wgTitle->getFullURL() );
448 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
449 }
450
451 function printFooter() {
452 return "<p>" . $this->printSource() .
453 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
454 }
455
456 function doAfterContent()
457 {
458 global $wgUser, $wgOut, $wgLang;
459 $fname = 'Skin::doAfterContent';
460 wfProfileIn( $fname );
461 wfProfileIn( $fname.'-1' );
462
463 $s = "\n</div><br style=\"clear:both\" />\n";
464 $s .= "\n<div id='footer'>";
465 $s .= '<table border="0" cellspacing="0"><tr>';
466
467 wfProfileOut( $fname.'-1' );
468 wfProfileIn( $fname.'-2' );
469
470 $qb = $this->qbSetting();
471 $shove = ($qb != 0);
472 $left = ($qb == 1 || $qb == 3);
473 if($wgLang->isRTL()) $left = !$left;
474
475 if ( $shove && $left ) { # Left
476 $s .= $this->getQuickbarCompensator();
477 }
478 wfProfileOut( $fname.'-2' );
479 wfProfileIn( $fname.'-3' );
480 $l = $wgLang->isRTL() ? 'right' : 'left';
481 $s .= "<td class='bottom' align='$l' valign='top'>";
482
483 $s .= $this->bottomLinks();
484 $s .= "\n<br />" . $this->mainPageLink()
485 . ' | ' . $this->aboutLink()
486 . ' | ' . $this->specialLink( 'recentchanges' )
487 . ' | ' . $this->searchForm()
488 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
489
490 $s .= "</td>";
491 if ( $shove && !$left ) { # Right
492 $s .= $this->getQuickbarCompensator();
493 }
494 $s .= "</tr></table>\n</div>\n</div>\n";
495
496 wfProfileOut( $fname.'-3' );
497 wfProfileIn( $fname.'-4' );
498 if ( 0 != $qb ) { $s .= $this->quickBar(); }
499 wfProfileOut( $fname.'-4' );
500 wfProfileOut( $fname );
501 return $s;
502 }
503
504 function pageTitleLinks()
505 {
506 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
507
508 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
509 $action = $wgRequest->getText( 'action' );
510
511 $s = $this->printableLink();
512 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
513
514 if ( $wgOut->isArticleRelated() ) {
515 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
516 $name = $wgTitle->getDBkey();
517 $link = wfEscapeHTML( Image::wfImageUrl( $name ) );
518 $style = $this->getInternalLinkAttributes( $link, $name );
519 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
520 }
521 # This will show the "Approve" link if $wgUseApproval=true;
522 if ( isset ( $wgUseApproval ) && $wgUseApproval )
523 {
524 $t = $wgTitle->getDBkey();
525 $name = 'Approve this article' ;
526 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
527 #wfEscapeHTML( wfImageUrl( $name ) );
528 $style = $this->getExternalLinkAttributes( $link, $name );
529 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
530 }
531 }
532 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
533 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
534 wfMsg( 'currentrev' ) );
535 }
536
537 if ( $wgUser->getNewtalk() ) {
538 # do not show "You have new messages" text when we are viewing our
539 # own talk page
540
541 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
542 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
543 $n =$wgUser->getName();
544 $tl = $this->makeKnownLink( $wgLang->getNsText(
545 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
546 wfMsg('newmessageslink') );
547 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
548 }
549 }
550
551 $undelete = $this->getUndeleteLink();
552 if( !empty( $undelete ) ) {
553 $s .= ' | '.$undelete;
554 }
555 return $s;
556 }
557
558 function getUndeleteLink() {
559 global $wgUser, $wgTitle, $wgLang, $action;
560 if( $wgUser->isSysop() &&
561 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
562 ($n = $wgTitle->isDeleted() ) ) {
563 return wfMsg( 'thisisdeleted',
564 $this->makeKnownLink(
565 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
566 wfMsg( 'restorelink', $n ) ) );
567 }
568 return '';
569 }
570
571 function printableLink()
572 {
573 global $wgOut, $wgFeedClasses, $wgRequest;
574
575 $baseurl = $_SERVER['REQUEST_URI'];
576 if( strpos( '?', $baseurl ) == false ) {
577 $baseurl .= '?';
578 } else {
579 $baseurl .= '&';
580 }
581 $baseurl = htmlspecialchars( $baseurl );
582 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
583
584 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
585 if( $wgOut->isSyndicated() ) {
586 foreach( $wgFeedClasses as $format => $class ) {
587 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
588 $s .= " | <a href=\"$feedurl\">{$format}</a>";
589 }
590 }
591 return $s;
592 }
593
594 function pageTitle()
595 {
596 global $wgOut, $wgTitle, $wgUser;
597
598 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
599 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
600 return $s;
601 }
602
603 function pageSubtitle()
604 {
605 global $wgOut;
606
607 $sub = $wgOut->getSubtitle();
608 if ( '' == $sub ) {
609 global $wgExtraSubtitle;
610 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
611 }
612 $subpages = $this->subPageSubtitle();
613 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
614 $s = "<p class='subtitle'>{$sub}</p>\n";
615 return $s;
616 }
617
618 function subPageSubtitle()
619 {
620 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
621 $subpages = '';
622 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
623 $ptext=$wgTitle->getPrefixedText();
624 if(preg_match('/\//',$ptext)) {
625 $links = explode('/',$ptext);
626 $c = 0;
627 $growinglink = '';
628 foreach($links as $link) {
629 $c++;
630 if ($c<count($links)) {
631 $growinglink .= $link;
632 $getlink = $this->makeLink( $growinglink, $link );
633 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
634 if ($c>1) {
635 $subpages .= ' | ';
636 } else {
637 $subpages .= '&lt; ';
638 }
639 $subpages .= $getlink;
640 $growinglink .= '/';
641 }
642 }
643 }
644 }
645 return $subpages;
646 }
647
648 function nameAndLogin()
649 {
650 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
651
652 $li = $wgLang->specialPage( 'Userlogin' );
653 $lo = $wgLang->specialPage( 'Userlogout' );
654
655 $s = '';
656 if ( 0 == $wgUser->getID() ) {
657 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
658 $n = $wgIP;
659
660 $tl = $this->makeKnownLink( $wgLang->getNsText(
661 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
662 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
663
664 $s .= $n . ' ('.$tl.')';
665 } else {
666 $s .= wfMsg('notloggedin');
667 }
668
669 $rt = $wgTitle->getPrefixedURL();
670 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
671 $q = '';
672 } else { $q = "returnto={$rt}"; }
673
674 $s .= "\n<br />" . $this->makeKnownLink( $li,
675 wfMsg( 'login' ), $q );
676 } else {
677 $n = $wgUser->getName();
678 $rt = $wgTitle->getPrefixedURL();
679 $tl = $this->makeKnownLink( $wgLang->getNsText(
680 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
681 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
682
683 $tl = " ({$tl})";
684
685 $s .= $this->makeKnownLink( $wgLang->getNsText(
686 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
687 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
688 "returnto={$rt}" ) . ' | ' .
689 $this->specialLink( 'preferences' );
690 }
691 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
692 wfMsg( 'help' ) );
693
694 return $s;
695 }
696
697 function getSearchLink() {
698 $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
699 return $searchPage->getLocalURL();
700 }
701
702 function escapeSearchLink() {
703 return htmlspecialchars( $this->getSearchLink() );
704 }
705
706 function searchForm()
707 {
708 global $wgRequest;
709 $search = $wgRequest->getText( 'search' );
710
711 $s = '<form name="search" class="inline" method="post" action="'
712 . $this->escapeSearchLink() . "\">\n"
713 . '<input type="text" name="search" size="19" value="'
714 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
715 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
716 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
717
718 return $s;
719 }
720
721 function topLinks()
722 {
723 global $wgOut;
724 $sep = " |\n";
725
726 $s = $this->mainPageLink() . $sep
727 . $this->specialLink( 'recentchanges' );
728
729 if ( $wgOut->isArticleRelated() ) {
730 $s .= $sep . $this->editThisPage()
731 . $sep . $this->historyLink();
732 }
733 # Many people don't like this dropdown box
734 #$s .= $sep . $this->specialPagesList();
735
736 return $s;
737 }
738
739 function bottomLinks()
740 {
741 global $wgOut, $wgUser, $wgTitle;
742 $sep = " |\n";
743
744 $s = '';
745 if ( $wgOut->isArticleRelated() ) {
746 $s .= '<strong>' . $this->editThisPage() . '</strong>';
747 if ( 0 != $wgUser->getID() ) {
748 $s .= $sep . $this->watchThisPage();
749 }
750 $s .= $sep . $this->talkLink()
751 . $sep . $this->historyLink()
752 . $sep . $this->whatLinksHere()
753 . $sep . $this->watchPageLinksLink();
754
755 if ( $wgTitle->getNamespace() == Namespace::getUser()
756 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
757
758 {
759 $id=User::idFromName($wgTitle->getText());
760 $ip=User::isIP($wgTitle->getText());
761
762 if($id || $ip) { # both anons and non-anons have contri list
763 $s .= $sep . $this->userContribsLink();
764 }
765 if ( 0 != $wgUser->getID() ) { # show only to signed in users
766 if($id) { # can only email non-anons
767 $s .= $sep . $this->emailUserLink();
768 }
769 }
770 }
771 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
772 $s .= "\n<br />" . $this->deleteThisPage() .
773 $sep . $this->protectThisPage() .
774 $sep . $this->moveThisPage();
775 }
776 $s .= "<br />\n" . $this->otherLanguages();
777 }
778 return $s;
779 }
780
781 function pageStats()
782 {
783 global $wgOut, $wgLang, $wgArticle, $wgRequest;
784 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
785
786 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
787 if ( ! $wgOut->isArticle() ) { return ''; }
788 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
789 if ( 0 == $wgArticle->getID() ) { return ''; }
790
791 $s = '';
792 if ( !$wgDisableCounters ) {
793 $count = $wgLang->formatNum( $wgArticle->getCount() );
794 if ( $count ) {
795 $s = wfMsg( 'viewcount', $count );
796 }
797 }
798
799 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
800 require_once("Credits.php");
801 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
802 } else {
803 $s .= $this->lastModified();
804 }
805
806 return $s . ' ' . $this->getCopyright();
807 }
808
809 function getCopyright() {
810 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
811
812
813 $oldid = $wgRequest->getVal( 'oldid' );
814 $diff = $wgRequest->getVal( 'diff' );
815
816 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
817 $msg = 'history_copyright';
818 } else {
819 $msg = 'copyright';
820 }
821
822 $out = '';
823 if( $wgRightsPage ) {
824 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
825 } elseif( $wgRightsUrl ) {
826 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
827 } else {
828 # Give up now
829 return $out;
830 }
831 $out .= wfMsg( $msg, $link );
832 return $out;
833 }
834
835 function getCopyrightIcon() {
836 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
837 $out = '';
838 if( $wgRightsIcon ) {
839 $icon = htmlspecialchars( $wgRightsIcon );
840 if( $wgRightsUrl ) {
841 $url = htmlspecialchars( $wgRightsUrl );
842 $out .= '<a href="'.$url.'">';
843 }
844 $text = htmlspecialchars( $wgRightsText );
845 $out .= "<img src=\"$icon\" alt='$text' />";
846 if( $wgRightsUrl ) {
847 $out .= '</a>';
848 }
849 }
850 return $out;
851 }
852
853 function getPoweredBy() {
854 global $wgStylePath;
855 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
856 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
857 return $img;
858 }
859
860 function lastModified()
861 {
862 global $wgLang, $wgArticle;
863
864 $timestamp = $wgArticle->getTimestamp();
865 if ( $timestamp ) {
866 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
867 $s = ' ' . wfMsg( 'lastmodified', $d );
868 } else {
869 $s = '';
870 }
871 return $s;
872 }
873
874 function logoText( $align = '' )
875 {
876 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
877 else { $a = ''; }
878
879 $mp = wfMsg( 'mainpage' );
880 $titleObj = Title::newFromText( $mp );
881 $s = '<a href="' . $titleObj->escapeLocalURL()
882 . '"><img'.$a.' src="'
883 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
884 return $s;
885 }
886
887 function quickBar()
888 {
889 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
890 global $wgDisableUploads, $wgRemoteUploads;
891
892 $fname = 'Skin::quickBar';
893 wfProfileIn( $fname );
894
895 $action = $wgRequest->getText( 'action' );
896 $wpPreview = $wgRequest->getBool( 'wpPreview' );
897 $tns=$wgTitle->getNamespace();
898
899 $s = "\n<div id='quickbar'>";
900 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
901
902 $sep = "\n<br />";
903 $s .= $this->mainPageLink()
904 . $sep . $this->specialLink( 'recentchanges' )
905 . $sep . $this->specialLink( 'randompage' );
906 if ($wgUser->getID()) {
907 $s.= $sep . $this->specialLink( 'watchlist' ) ;
908 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
909 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
910
911 }
912 // only show watchlist link if logged in
913 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
914 $s .= "\n<br /><hr class='sep' />";
915 $articleExists = $wgTitle->getArticleId();
916 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
917 if($wgOut->isArticle()) {
918 $s .= '<strong>' . $this->editThisPage() . '</strong>';
919 } else { # backlink to the article in edit or history mode
920 if($articleExists){ # no backlink if no article
921 switch($tns) {
922 case 0:
923 $text = wfMsg('articlepage');
924 break;
925 case 1:
926 $text = wfMsg('viewtalkpage');
927 break;
928 case 2:
929 $text = wfMsg('userpage');
930 break;
931 case 3:
932 $text = wfMsg('viewtalkpage');
933 break;
934 case 4:
935 $text = wfMsg('wikipediapage');
936 break;
937 case 5:
938 $text = wfMsg('viewtalkpage');
939 break;
940 case 6:
941 $text = wfMsg('imagepage');
942 break;
943 case 7:
944 $text = wfMsg('viewtalkpage');
945 break;
946 default:
947 $text= wfMsg('articlepage');
948 }
949
950 $link = $wgTitle->getText();
951 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
952 $link = $nstext . ':' . $link ;
953 }
954
955 $s .= $this->makeLink( $link, $text );
956 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
957 # we just throw in a "New page" text to tell the user that he's in edit mode,
958 # and to avoid messing with the separator that is prepended to the next item
959 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
960 }
961
962 }
963
964
965 if( $tns%2 && $action!='edit' && !$wpPreview) {
966 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
967 }
968
969 /*
970 watching could cause problems in edit mode:
971 if user edits article, then loads "watch this article" in background and then saves
972 article with "Watch this article" checkbox disabled, the article is transparently
973 unwatched. Therefore we do not show the "Watch this page" link in edit mode
974 */
975 if ( 0 != $wgUser->getID() && $articleExists) {
976 if($action!='edit' && $action != 'submit' )
977 {
978 $s .= $sep . $this->watchThisPage();
979 }
980 if ( $wgTitle->userCanEdit() )
981 $s .= $sep . $this->moveThisPage();
982 }
983 if ( $wgUser->isSysop() and $articleExists ) {
984 $s .= $sep . $this->deleteThisPage() .
985 $sep . $this->protectThisPage();
986 }
987 $s .= $sep . $this->talkLink();
988 if ($articleExists && $action !='history') {
989 $s .= $sep . $this->historyLink();
990 }
991 $s.=$sep . $this->whatLinksHere();
992
993 if($wgOut->isArticleRelated()) {
994 $s .= $sep . $this->watchPageLinksLink();
995 }
996
997 if ( Namespace::getUser() == $wgTitle->getNamespace()
998 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
999 ) {
1000
1001 $id=User::idFromName($wgTitle->getText());
1002 $ip=User::isIP($wgTitle->getText());
1003
1004 if($id||$ip) {
1005 $s .= $sep . $this->userContribsLink();
1006 }
1007 if ( 0 != $wgUser->getID() ) {
1008 if($id) { # can only email real users
1009 $s .= $sep . $this->emailUserLink();
1010 }
1011 }
1012 }
1013 $s .= "\n<br /><hr class='sep' />";
1014 }
1015
1016 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1017 $s .= $this->specialLink( 'upload' ) . $sep;
1018 }
1019 $s .= $this->specialLink( 'specialpages' )
1020 . $sep . $this->bugReportsLink();
1021
1022 global $wgSiteSupportPage;
1023 if( $wgSiteSupportPage ) {
1024 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1025 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1026 }
1027
1028 $s .= "\n<br /></div>\n";
1029 wfProfileOut( $fname );
1030 return $s;
1031 }
1032
1033 function specialPagesList()
1034 {
1035 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1036 require_once('SpecialPage.php');
1037 $a = array();
1038 $pages = SpecialPage::getPages();
1039
1040 foreach ( $pages[''] as $name => $page ) {
1041 $a[$name] = $page->getDescription();
1042 }
1043 if ( $wgUser->isSysop() )
1044 {
1045 foreach ( $pages['sysop'] as $name => $page ) {
1046 $a[$name] = $page->getDescription();
1047 }
1048 }
1049 if ( $wgUser->isDeveloper() )
1050 {
1051 foreach ( $pages['developer'] as $name => $page ) {
1052 $a[$name] = $page->getDescription() ;
1053 }
1054 }
1055 $go = wfMsg( 'go' );
1056 $sp = wfMsg( 'specialpages' );
1057 $spp = $wgLang->specialPage( 'Specialpages' );
1058
1059 $s = '<form id="specialpages" method="get" class="inline" ' .
1060 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1061 $s .= "<select name=\"wpDropdown\">\n";
1062 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1063
1064 foreach ( $a as $name => $desc ) {
1065 $p = $wgLang->specialPage( $name );
1066 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1067 }
1068 $s .= "</select>\n";
1069 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1070 $s .= "</form>\n";
1071 return $s;
1072 }
1073
1074 function mainPageLink()
1075 {
1076 $mp = wfMsg( 'mainpage' );
1077 $s = $this->makeKnownLink( $mp, $mp );
1078 return $s;
1079 }
1080
1081 function copyrightLink()
1082 {
1083 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1084 wfMsg( 'copyrightpagename' ) );
1085 return $s;
1086 }
1087
1088 function aboutLink()
1089 {
1090 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1091 wfMsg( 'aboutwikipedia' ) );
1092 return $s;
1093 }
1094
1095
1096 function disclaimerLink()
1097 {
1098 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1099 wfMsg( 'disclaimers' ) );
1100 return $s;
1101 }
1102
1103 function editThisPage()
1104 {
1105 global $wgOut, $wgTitle, $wgRequest;
1106
1107 $oldid = $wgRequest->getVal( 'oldid' );
1108 $diff = $wgRequest->getVal( 'diff' );
1109 $redirect = $wgRequest->getVal( 'redirect' );
1110
1111 if ( ! $wgOut->isArticleRelated() ) {
1112 $s = wfMsg( 'protectedpage' );
1113 } else {
1114 $n = $wgTitle->getPrefixedText();
1115 if ( $wgTitle->userCanEdit() ) {
1116 $t = wfMsg( 'editthispage' );
1117 } else {
1118 #$t = wfMsg( "protectedpage" );
1119 $t = wfMsg( 'viewsource' );
1120 }
1121 $oid = $red = '';
1122
1123 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1124 if ( $oldid && ! isset( $diff ) ) {
1125 $oid = "&oldid={$oldid}";
1126 }
1127 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1128 }
1129 return $s;
1130 }
1131
1132 function deleteThisPage()
1133 {
1134 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1135
1136 $diff = $wgRequest->getVal( 'diff' );
1137 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1138 $n = $wgTitle->getPrefixedText();
1139 $t = wfMsg( 'deletethispage' );
1140
1141 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1142 } else {
1143 $s = '';
1144 }
1145 return $s;
1146 }
1147
1148 function protectThisPage()
1149 {
1150 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1151
1152 $diff = $wgRequest->getVal( 'diff' );
1153 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1154 $n = $wgTitle->getPrefixedText();
1155
1156 if ( $wgTitle->isProtected() ) {
1157 $t = wfMsg( 'unprotectthispage' );
1158 $q = 'action=unprotect';
1159 } else {
1160 $t = wfMsg( 'protectthispage' );
1161 $q = 'action=protect';
1162 }
1163 $s = $this->makeKnownLink( $n, $t, $q );
1164 } else {
1165 $s = '';
1166 }
1167 return $s;
1168 }
1169
1170 function watchThisPage()
1171 {
1172 global $wgUser, $wgOut, $wgTitle;
1173
1174 if ( $wgOut->isArticleRelated() ) {
1175 $n = $wgTitle->getPrefixedText();
1176
1177 if ( $wgTitle->userIsWatching() ) {
1178 $t = wfMsg( 'unwatchthispage' );
1179 $q = 'action=unwatch';
1180 } else {
1181 $t = wfMsg( 'watchthispage' );
1182 $q = 'action=watch';
1183 }
1184 $s = $this->makeKnownLink( $n, $t, $q );
1185 } else {
1186 $s = wfMsg( 'notanarticle' );
1187 }
1188 return $s;
1189 }
1190
1191 function moveThisPage()
1192 {
1193 global $wgTitle, $wgLang;
1194
1195 if ( $wgTitle->userCanEdit() ) {
1196 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1197 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1198 } // no message if page is protected - would be redundant
1199 return $s;
1200 }
1201
1202 function historyLink()
1203 {
1204 global $wgTitle;
1205
1206 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1207 wfMsg( 'history' ), 'action=history' );
1208 return $s;
1209 }
1210
1211 function whatLinksHere()
1212 {
1213 global $wgTitle, $wgLang;
1214
1215 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1216 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1217 return $s;
1218 }
1219
1220 function userContribsLink()
1221 {
1222 global $wgTitle, $wgLang;
1223
1224 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1225 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1226 return $s;
1227 }
1228
1229 function emailUserLink()
1230 {
1231 global $wgTitle, $wgLang;
1232
1233 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1234 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1235 return $s;
1236 }
1237
1238 function watchPageLinksLink()
1239 {
1240 global $wgOut, $wgTitle, $wgLang;
1241
1242 if ( ! $wgOut->isArticleRelated() ) {
1243 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1244 } else {
1245 $s = $this->makeKnownLink( $wgLang->specialPage(
1246 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1247 'target=' . $wgTitle->getPrefixedURL() );
1248 }
1249 return $s;
1250 }
1251
1252 function otherLanguages()
1253 {
1254 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1255
1256 $a = $wgOut->getLanguageLinks();
1257 if ( 0 == count( $a ) ) {
1258 if ( !$wgUseNewInterlanguage ) return '';
1259 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1260 if ( $ns != 0 AND $ns != 1 ) return '' ;
1261 $pn = 'Intl' ;
1262 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1263 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1264 wfMsg( 'intl' ) , $x );
1265 }
1266
1267 if ( !$wgUseNewInterlanguage ) {
1268 $s = wfMsg( 'otherlanguages' ) . ': ';
1269 } else {
1270 global $wgLanguageCode ;
1271 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1272 $x .= '&xl='.$wgLanguageCode ;
1273 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1274 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1275 }
1276
1277 $s = wfMsg( 'otherlanguages' ) . ': ';
1278 $first = true;
1279 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1280 foreach( $a as $l ) {
1281 if ( ! $first ) { $s .= ' | '; }
1282 $first = false;
1283
1284 $nt = Title::newFromText( $l );
1285 $url = $nt->getFullURL();
1286 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1287
1288 if ( '' == $text ) { $text = $l; }
1289 $style = $this->getExternalLinkAttributes( $l, $text );
1290 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1291 }
1292 if($wgLang->isRTL()) $s .= '</span>';
1293 return $s;
1294 }
1295
1296 function bugReportsLink()
1297 {
1298 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1299 wfMsg( 'bugreports' ) );
1300 return $s;
1301 }
1302
1303 function dateLink()
1304 {
1305 global $wgLinkCache;
1306 $t1 = Title::newFromText( gmdate( 'F j' ) );
1307 $t2 = Title::newFromText( gmdate( 'Y' ) );
1308
1309 $wgLinkCache->suspend();
1310 $id = $t1->getArticleID();
1311 $wgLinkCache->resume();
1312
1313 if ( 0 == $id ) {
1314 $s = $this->makeBrokenLink( $t1->getText() );
1315 } else {
1316 $s = $this->makeKnownLink( $t1->getText() );
1317 }
1318 $s .= ', ';
1319
1320 $wgLinkCache->suspend();
1321 $id = $t2->getArticleID();
1322 $wgLinkCache->resume();
1323
1324 if ( 0 == $id ) {
1325 $s .= $this->makeBrokenLink( $t2->getText() );
1326 } else {
1327 $s .= $this->makeKnownLink( $t2->getText() );
1328 }
1329 return $s;
1330 }
1331
1332 function talkLink()
1333 {
1334 global $wgLang, $wgTitle, $wgLinkCache;
1335
1336 $tns = $wgTitle->getNamespace();
1337 if ( -1 == $tns ) { return ''; }
1338
1339 $pn = $wgTitle->getText();
1340 $tp = wfMsg( 'talkpage' );
1341 if ( Namespace::isTalk( $tns ) ) {
1342 $lns = Namespace::getSubject( $tns );
1343 switch($tns) {
1344 case 1:
1345 $text = wfMsg('articlepage');
1346 break;
1347 case 3:
1348 $text = wfMsg('userpage');
1349 break;
1350 case 5:
1351 $text = wfMsg('wikipediapage');
1352 break;
1353 case 7:
1354 $text = wfMsg('imagepage');
1355 break;
1356 default:
1357 $text= wfMsg('articlepage');
1358 }
1359 } else {
1360
1361 $lns = Namespace::getTalk( $tns );
1362 $text=$tp;
1363 }
1364 $n = $wgLang->getNsText( $lns );
1365 if ( '' == $n ) { $link = $pn; }
1366 else { $link = $n.':'.$pn; }
1367
1368 $wgLinkCache->suspend();
1369 $s = $this->makeLink( $link, $text );
1370 $wgLinkCache->resume();
1371
1372 return $s;
1373 }
1374
1375 function commentLink()
1376 {
1377 global $wgLang, $wgTitle, $wgLinkCache;
1378
1379 $tns = $wgTitle->getNamespace();
1380 if ( -1 == $tns ) { return ''; }
1381
1382 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1383
1384 # assert Namespace::isTalk( $lns )
1385
1386 $n = $wgLang->getNsText( $lns );
1387 $pn = $wgTitle->getText();
1388
1389 $link = $n.':'.$pn;
1390
1391 $wgLinkCache->suspend();
1392 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1393 $wgLinkCache->resume();
1394
1395 return $s;
1396 }
1397
1398 # After all the page content is transformed into HTML, it makes
1399 # a final pass through here for things like table backgrounds.
1400 #
1401 function transformContent( $text )
1402 {
1403 return $text;
1404 }
1405
1406 # Note: This function MUST call getArticleID() on the link,
1407 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1408 #
1409 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1410 wfProfileIn( 'Skin::makeLink' );
1411 $nt = Title::newFromText( $title );
1412 if ($nt) {
1413 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1414 } else {
1415 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1416 $result = $text == "" ? $title : $text;
1417 }
1418
1419 wfProfileOut( 'Skin::makeLink' );
1420 return $result;
1421 }
1422
1423 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1424 $nt = Title::newFromText( $title );
1425 if ($nt) {
1426 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1427 } else {
1428 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1429 return $text == '' ? $title : $text;
1430 }
1431 }
1432
1433 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1434 $nt = Title::newFromText( $title );
1435 if ($nt) {
1436 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1437 } else {
1438 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1439 return $text == '' ? $title : $text;
1440 }
1441 }
1442
1443 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1444 $nt = Title::newFromText( $title );
1445 if ($nt) {
1446 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1447 } else {
1448 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1449 return $text == '' ? $title : $text;
1450 }
1451 }
1452
1453 # Pass a title object, not a title string
1454 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1455 {
1456 global $wgOut, $wgUser;
1457 $fname = 'Skin::makeLinkObj';
1458
1459 # Fail gracefully
1460 if ( ! isset($nt) )
1461 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1462
1463 if ( $nt->isExternal() ) {
1464 $u = $nt->getFullURL();
1465 $link = $nt->getPrefixedURL();
1466 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1467 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1468
1469 $inside = '';
1470 if ( '' != $trail ) {
1471 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1472 $inside = $m[1];
1473 $trail = $m[2];
1474 }
1475 }
1476 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1477 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1478 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1479 } elseif ( ( -1 == $nt->getNamespace() ) ||
1480 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1481 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1482 } else {
1483 if ( $this->postParseLinkColour() ) {
1484 $inside = '';
1485 if ( '' != $trail ) {
1486 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1487 $inside = $m[1];
1488 $trail = $m[2];
1489 }
1490 }
1491
1492 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1493 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1494 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1495 } else {
1496 # Work out link colour immediately
1497 $aid = $nt->getArticleID() ;
1498 if ( 0 == $aid ) {
1499 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1500 } else {
1501 $threshold = $wgUser->getOption('stubthreshold') ;
1502 if ( $threshold > 0 ) {
1503 $dbr =& wfGetDB( DB_SLAVE );
1504 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1505 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1506 if ( $s !== false ) {
1507 $size = $s->x;
1508 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1509 $size = $threshold*2 ; # Really big
1510 }
1511 $dbr->freeResult( $res );
1512 } else {
1513 $size = $threshold*2 ; # Really big
1514 }
1515 } else {
1516 $size = 1 ;
1517 }
1518 if ( $size < $threshold ) {
1519 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1520 } else {
1521 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1522 }
1523 }
1524 }
1525 }
1526 return $retVal;
1527 }
1528
1529 # Pass a title object, not a title string
1530 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1531 {
1532 global $wgOut, $wgTitle, $wgInputEncoding;
1533
1534 $fname = 'Skin::makeKnownLinkObj';
1535 wfProfileIn( $fname );
1536
1537 if ( !is_object( $nt ) ) {
1538 return $text;
1539 }
1540 $link = $nt->getPrefixedURL();
1541
1542 if ( '' == $link ) {
1543 $u = '';
1544 if ( '' == $text ) {
1545 $text = htmlspecialchars( $nt->getFragment() );
1546 }
1547 } else {
1548 $u = $nt->escapeLocalURL( $query );
1549 }
1550 if ( '' != $nt->getFragment() ) {
1551 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1552 $replacearray = array(
1553 '%3A' => ':',
1554 '%' => '.'
1555 );
1556 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1557 }
1558 if ( '' == $text ) {
1559 $text = htmlspecialchars( $nt->getPrefixedText() );
1560 }
1561 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1562
1563 $inside = '';
1564 if ( '' != $trail ) {
1565 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1566 $inside = $m[1];
1567 $trail = $m[2];
1568 }
1569 }
1570 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1571 wfProfileOut( $fname );
1572 return $r;
1573 }
1574
1575 # Pass a title object, not a title string
1576 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1577 {
1578 global $wgOut, $wgUser;
1579
1580 $fname = 'Skin::makeBrokenLinkObj';
1581 wfProfileIn( $fname );
1582
1583 if ( '' == $query ) {
1584 $q = 'action=edit';
1585 } else {
1586 $q = 'action=edit&'.$query;
1587 }
1588 $u = $nt->escapeLocalURL( $q );
1589
1590 if ( '' == $text ) {
1591 $text = htmlspecialchars( $nt->getPrefixedText() );
1592 }
1593 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1594
1595 $inside = '';
1596 if ( '' != $trail ) {
1597 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1598 $inside = $m[1];
1599 $trail = $m[2];
1600 }
1601 }
1602 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1603 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1604 } else {
1605 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1606 }
1607
1608 wfProfileOut( $fname );
1609 return $s;
1610 }
1611
1612 # Pass a title object, not a title string
1613 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1614 {
1615 global $wgOut, $wgUser;
1616
1617 $link = $nt->getPrefixedURL();
1618
1619 $u = $nt->escapeLocalURL( $query );
1620
1621 if ( '' == $text ) {
1622 $text = htmlspecialchars( $nt->getPrefixedText() );
1623 }
1624 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1625
1626 $inside = '';
1627 if ( '' != $trail ) {
1628 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1629 $inside = $m[1];
1630 $trail = $m[2];
1631 }
1632 }
1633 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1634 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1635 } else {
1636 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1637 }
1638 return $s;
1639 }
1640
1641 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1642 {
1643 $u = $nt->escapeLocalURL( $query );
1644 if ( '' == $text ) {
1645 $text = htmlspecialchars( $nt->getPrefixedText() );
1646 }
1647 $inside = '';
1648 if ( '' != $trail ) {
1649 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1650 $inside = $m[1];
1651 $trail = $m[2];
1652 }
1653 }
1654 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1655 }
1656
1657 /* these are used extensively in SkinPHPTal, but also some other places */
1658 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1659 $title = Title::makeTitle( NS_SPECIAL, $name );
1660 $this->checkTitle($title, $name);
1661 return $title->getLocalURL( $urlaction );
1662 }
1663 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1664 $title = Title::newFromText( $name );
1665 $title = $title->getTalkPage();
1666 $this->checkTitle($title, $name);
1667 return $title->getLocalURL( $urlaction );
1668 }
1669 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1670 $title = Title::newFromText( $name );
1671 $title= $title->getSubjectPage();
1672 $this->checkTitle($title, $name);
1673 return $title->getLocalURL( $urlaction );
1674 }
1675 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1676 $title = Title::newFromText( wfMsg($name) );
1677 $this->checkTitle($title, $name);
1678 return $title->getLocalURL( $urlaction );
1679 }
1680 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1681 $title = Title::newFromText( $name );
1682 $this->checkTitle($title, $name);
1683 return $title->getLocalURL( $urlaction );
1684 }
1685 # this can be passed the NS number as defined in Language.php
1686 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1687 $title = Title::makeTitle( $namespace, $name );
1688 $this->checkTitle($title, $name);
1689 return $title->getLocalURL( $urlaction );
1690 }
1691
1692 /* these return an array with the 'href' and boolean 'exists' */
1693 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1694 $title = Title::newFromText( $name );
1695 $this->checkTitle($title, $name);
1696 return array(
1697 'href' => $title->getLocalURL( $urlaction ),
1698 'exists' => $title->getArticleID() != 0?true:false
1699 );
1700 }
1701 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1702 $title = Title::newFromText( $name );
1703 $title = $title->getTalkPage();
1704 $this->checkTitle($title, $name);
1705 return array(
1706 'href' => $title->getLocalURL( $urlaction ),
1707 'exists' => $title->getArticleID() != 0?true:false
1708 );
1709 }
1710 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1711 $title = Title::newFromText( $name );
1712 $title= $title->getSubjectPage();
1713 $this->checkTitle($title, $name);
1714 return array(
1715 'href' => $title->getLocalURL( $urlaction ),
1716 'exists' => $title->getArticleID() != 0?true:false
1717 );
1718 }
1719 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1720 $title = Title::newFromText( wfMsg($name) );
1721 $this->checkTitle($title, $name);
1722 return array(
1723 'href' => $title->getLocalURL( $urlaction ),
1724 'exists' => $title->getArticleID() != 0?true:false
1725 );
1726 }
1727
1728 # make sure we have some title to operate on
1729 /*static*/ function checkTitle ( &$title, &$name ) {
1730 if(!is_object($title)) {
1731 $title = Title::newFromText( $name );
1732 if(!is_object($title)) {
1733 $title = Title::newFromText( '--error: link target missing--' );
1734 }
1735 }
1736 }
1737
1738 function fnamePart( $url )
1739 {
1740 $basename = strrchr( $url, '/' );
1741 if ( false === $basename ) { $basename = $url; }
1742 else { $basename = substr( $basename, 1 ); }
1743 return wfEscapeHTML( $basename );
1744 }
1745
1746 function makeImage( $url, $alt = '' )
1747 {
1748 global $wgOut;
1749
1750 if ( '' == $alt ) { $alt = $this->fnamePart( $url ); }
1751 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1752 return $s;
1753 }
1754
1755 function makeImageLink( $name, $url, $alt = '' ) {
1756 $nt = Title::makeTitle( Namespace::getImage(), $name );
1757 return $this->makeImageLinkObj( $nt, $alt );
1758 }
1759
1760 function makeImageLinkObj( $nt, $alt = '' ) {
1761 global $wgLang, $wgUseImageResize;
1762 $img = Image::newFromTitle( $nt );
1763 $url = $img->getURL();
1764
1765 $align = '';
1766 $prefix = $postfix = '';
1767
1768 if ( $wgUseImageResize ) {
1769 # Check if the alt text is of the form "options|alt text"
1770 # Options are:
1771 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1772 # * left no resizing, just left align. label is used for alt= only
1773 # * right same, but right aligned
1774 # * none same, but not aligned
1775 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1776 # * center center the image
1777 # * framed Keep original image size, no magnify-button.
1778
1779 $part = explode( '|', $alt);
1780
1781 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1782 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1783 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1784 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1785 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1786 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1787 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1788 $alt = $part[count($part)-1];
1789
1790 $height = $framed = $thumb = false;
1791 $manual_thumb = "" ;
1792
1793 foreach( $part as $key => $val ) {
1794 $val_parts = explode ( "=" , $val , 2 ) ;
1795 $left_part = array_shift ( $val_parts ) ;
1796 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1797 $thumb=true;
1798 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1799 # use manually specified thumbnail
1800 $thumb=true;
1801 $manual_thumb = array_shift ( $val_parts ) ;
1802 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1803 # remember to set an alignment, don't render immediately
1804 $align = 'right';
1805 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1806 # remember to set an alignment, don't render immediately
1807 $align = 'left';
1808 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1809 # remember to set an alignment, don't render immediately
1810 $align = 'center';
1811 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1812 # remember to set an alignment, don't render immediately
1813 $align = 'none';
1814 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1815 # $match is the image width in pixels
1816 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1817 $width = intval( $m[1] );
1818 $height = intval( $m[2] );
1819 } else {
1820 $width = intval($match);
1821 }
1822 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1823 $framed=true;
1824 }
1825 }
1826 if ( 'center' == $align )
1827 {
1828 $prefix = '<span style="text-align: center">';
1829 $postfix = '</span>';
1830 $align = 'none';
1831 }
1832
1833 if ( $thumb || $framed ) {
1834
1835 # Create a thumbnail. Alignment depends on language
1836 # writing direction, # right aligned for left-to-right-
1837 # languages ("Western languages"), left-aligned
1838 # for right-to-left-languages ("Semitic languages")
1839 #
1840 # If thumbnail width has not been provided, it is set
1841 # here to 180 pixels
1842 if ( $align == '' ) {
1843 $align = $wgLang->isRTL() ? 'left' : 'right';
1844 }
1845 if ( ! isset($width) ) {
1846 $width = 180;
1847 }
1848 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1849
1850 } elseif ( isset($width) ) {
1851
1852 # Create a resized image, without the additional thumbnail
1853 # features
1854
1855 if ( ( ! $height === false )
1856 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1857 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1858 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1859 $width = $img->getWidth() * $height / $img->getHeight();
1860 }
1861 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1862 }
1863 } # endif $wgUseImageResize
1864
1865 if ( empty( $alt ) ) {
1866 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1867 }
1868 $alt = htmlspecialchars( $alt );
1869
1870 $u = $nt->escapeLocalURL();
1871 if ( $url == '' )
1872 {
1873 $s = wfMsg( 'missingimage', $img->getName() );
1874 $s .= "<br>{$alt}<br>{$url}<br>\n";
1875 } else {
1876 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1877 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1878 }
1879 if ( '' != $align ) {
1880 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1881 }
1882 return str_replace("\n", ' ',$prefix.$s.$postfix);
1883 }
1884
1885 # Make HTML for a thumbnail including image, border and caption
1886 # $img is an Image object
1887 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1888 global $wgStylePath, $wgLang;
1889 # $image = Title::makeTitle( Namespace::getImage(), $name );
1890 $url = $img->getURL();
1891
1892 #$label = htmlspecialchars( $label );
1893 $alt = preg_replace( '/<[^>]*>/', '', $label);
1894 $alt = htmlspecialchars( $alt );
1895
1896 $width = $height = 0;
1897 if ( $img->exists() )
1898 {
1899 $width = $img->getWidth();
1900 $height = $img->getHeight();
1901 }
1902 if ( 0 == $width || 0 == $height )
1903 {
1904 $width = $height = 200;
1905 }
1906 if ( $boxwidth == 0 )
1907 {
1908 $boxwidth = 200;
1909 }
1910 if ( $framed )
1911 {
1912 // Use image dimensions, don't scale
1913 $boxwidth = $width;
1914 $oboxwidth = $boxwidth + 2;
1915 $boxheight = $height;
1916 $thumbUrl = $url;
1917 } else {
1918 $h = intval( $height/($width/$boxwidth) );
1919 $oboxwidth = $boxwidth + 2;
1920 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1921 {
1922 $boxwidth *= $boxheight/$h;
1923 } else {
1924 $boxheight = $h;
1925 }
1926 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1927 }
1928
1929 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1930 {
1931 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1932 $manual_img = Image::newFromTitle( $manual_title );
1933 $thumbUrl = $manual_img->getURL();
1934 if ( $manual_img->exists() )
1935 {
1936 $width = $manual_img->getWidth();
1937 $height = $manual_img->getHeight();
1938 $boxwidth = $width ;
1939 $boxheight = $height ;
1940 $oboxwidth = $boxwidth + 2 ;
1941 }
1942 }
1943
1944 $u = $img->getEscapeLocalURL();
1945
1946 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1947 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1948 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1949
1950 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1951 if ( $thumbUrl == '' ) {
1952 $s .= wfMsg( 'missingimage', $img->getName() );
1953 $zoomicon = '';
1954 } else {
1955 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1956 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1957 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1958 if ( $framed ) {
1959 $zoomicon="";
1960 } else {
1961 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1962 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1963 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1964 'width="15" height="11" alt="'.$more.'" /></a></div>';
1965 }
1966 }
1967 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1968 return str_replace("\n", ' ', $s);
1969 }
1970
1971 function makeMediaLink( $name, $url, $alt = "" ) {
1972 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1973 return $this->makeMediaLinkObj( $nt, $alt );
1974 }
1975
1976 function makeMediaLinkObj( $nt, $alt = "" )
1977 {
1978 if ( ! isset( $nt ) )
1979 {
1980 ### HOTFIX. Instead of breaking, return empty string.
1981 $s = $alt;
1982 } else {
1983 $name = $nt->getDBKey();
1984 $url = Image::wfImageUrl( $name );
1985 if ( empty( $alt ) ) {
1986 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1987 }
1988
1989 $u = htmlspecialchars( $url );
1990 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1991 }
1992 return $s;
1993 }
1994
1995 function specialLink( $name, $key = "" )
1996 {
1997 global $wgLang;
1998
1999 if ( '' == $key ) { $key = strtolower( $name ); }
2000 $pn = $wgLang->ucfirst( $name );
2001 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2002 wfMsg( $key ) );
2003 }
2004
2005 function makeExternalLink( $url, $text, $escape = true ) {
2006 $style = $this->getExternalLinkAttributes( $url, $text );
2007 $url = htmlspecialchars( $url );
2008 if( $escape ) {
2009 $text = htmlspecialchars( $text );
2010 }
2011 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2012 }
2013
2014 # Called by history lists and recent changes
2015 #
2016
2017 # Returns text for the start of the tabular part of RC
2018 function beginRecentChangesList()
2019 {
2020 $this->rc_cache = array() ;
2021 $this->rcMoveIndex = 0;
2022 $this->rcCacheIndex = 0 ;
2023 $this->lastdate = '';
2024 $this->rclistOpen = false;
2025 return '';
2026 }
2027
2028 function beginImageHistoryList()
2029 {
2030 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2031 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2032 return $s;
2033 }
2034
2035 # Returns text for the end of RC
2036 # If enhanced RC is in use, returns pretty much all the text
2037 function endRecentChangesList()
2038 {
2039 $s = $this->recentChangesBlock() ;
2040 if( $this->rclistOpen ) {
2041 $s .= "</ul>\n";
2042 }
2043 return $s;
2044 }
2045
2046 # Enhanced RC ungrouped line
2047 function recentChangesBlockLine ( $rcObj )
2048 {
2049 global $wgStylePath, $wgLang ;
2050
2051 # Get rc_xxxx variables
2052 extract( $rcObj->mAttribs ) ;
2053 $curIdEq = 'curid='.$rc_cur_id;
2054
2055 # Spacer image
2056 $r = '' ;
2057
2058 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2059 $r .= '<tt>' ;
2060
2061 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2062 $r .= '&nbsp;&nbsp;';
2063 } else {
2064 # M & N (minor & new)
2065 $M = wfMsg( 'minoreditletter' );
2066 $N = wfMsg( 'newpageletter' );
2067
2068 if ( $rc_type == RC_NEW ) {
2069 $r .= $N ;
2070 } else {
2071 $r .= '&nbsp;' ;
2072 }
2073 if ( $rc_minor ) {
2074 $r .= $M ;
2075 } else {
2076 $r .= '&nbsp;' ;
2077 }
2078 }
2079
2080 # Timestamp
2081 $r .= ' '.$rcObj->timestamp.' ' ;
2082 $r .= '</tt>' ;
2083
2084 # Article link
2085 $link = $rcObj->link ;
2086 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2087 $r .= $link ;
2088
2089 # Diff
2090 $r .= ' (' ;
2091 $r .= $rcObj->difflink ;
2092 $r .= '; ' ;
2093
2094 # Hist
2095 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2096
2097 # User/talk
2098 $r .= ') . . '.$rcObj->userlink ;
2099 $r .= $rcObj->usertalklink ;
2100
2101 # Comment
2102 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2103 $rc_comment=$this->formatComment($rc_comment);
2104 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2105 }
2106
2107 $r .= "<br />\n" ;
2108 return $r ;
2109 }
2110
2111 # Enhanced RC group
2112 function recentChangesBlockGroup ( $block )
2113 {
2114 global $wgStylePath, $wgLang ;
2115
2116 $r = '' ;
2117 $M = wfMsg( 'minoreditletter' );
2118 $N = wfMsg( 'newpageletter' );
2119
2120 # Collate list of users
2121 $isnew = false ;
2122 $userlinks = array () ;
2123 foreach ( $block AS $rcObj ) {
2124 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2125 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2126 $u = $rcObj->userlink ;
2127 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2128 $userlinks[$u]++ ;
2129 }
2130
2131 # Sort the list and convert to text
2132 krsort ( $userlinks ) ;
2133 asort ( $userlinks ) ;
2134 $users = array () ;
2135 foreach ( $userlinks as $userlink => $count) {
2136 $text = $userlink ;
2137 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2138 array_push ( $users , $text ) ;
2139 }
2140 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2141
2142 # Arrow
2143 $rci = 'RCI'.$this->rcCacheIndex ;
2144 $rcl = 'RCL'.$this->rcCacheIndex ;
2145 $rcm = 'RCM'.$this->rcCacheIndex ;
2146 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2147 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2148 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2149 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2150 $r .= $tl ;
2151
2152 # Main line
2153 # M/N
2154 $r .= '<tt>' ;
2155 if ( $isnew ) $r .= $N ;
2156 else $r .= '&nbsp;' ;
2157 $r .= '&nbsp;' ; # Minor
2158
2159 # Timestamp
2160 $r .= ' '.$block[0]->timestamp.' ' ;
2161 $r .= '</tt>' ;
2162
2163 # Article link
2164 $link = $block[0]->link ;
2165 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2166 $r .= $link ;
2167
2168 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2169 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2170 # Changes
2171 $r .= ' ('.count($block).' ' ;
2172 if ( $isnew ) $r .= wfMsg('changes');
2173 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2174 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2175 $r .= '; ' ;
2176
2177 # History
2178 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2179 $r .= ')' ;
2180 }
2181
2182 $r .= $users ;
2183 $r .= "<br />\n" ;
2184
2185 # Sub-entries
2186 $r .= '<div id="'.$rci.'" style="display:none">' ;
2187 foreach ( $block AS $rcObj ) {
2188 # Get rc_xxxx variables
2189 extract( $rcObj->mAttribs );
2190
2191 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2192 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2193 if ( $rc_new ) $r .= $N ;
2194 else $r .= '&nbsp;' ;
2195 if ( $rc_minor ) $r .= $M ;
2196 else $r .= '&nbsp;' ;
2197 $r .= '</tt>' ;
2198
2199 $o = '' ;
2200 if ( $rc_last_oldid != 0 ) {
2201 $o = 'oldid='.$rc_last_oldid ;
2202 }
2203 if ( $rc_type == RC_LOG ) {
2204 $link = $rcObj->timestamp ;
2205 } else {
2206 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2207 }
2208 $link = '<tt>'.$link.'</tt>' ;
2209
2210 $r .= $link ;
2211 $r .= ' (' ;
2212 $r .= $rcObj->curlink ;
2213 $r .= '; ' ;
2214 $r .= $rcObj->lastlink ;
2215 $r .= ') . . '.$rcObj->userlink ;
2216 $r .= $rcObj->usertalklink ;
2217 if ( $rc_comment != '' ) {
2218 $rc_comment=$this->formatComment($rc_comment);
2219 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2220 }
2221 $r .= "<br />\n" ;
2222 }
2223 $r .= "</div>\n" ;
2224
2225 $this->rcCacheIndex++ ;
2226 return $r ;
2227 }
2228
2229 # If enhanced RC is in use, this function takes the previously cached
2230 # RC lines, arranges them, and outputs the HTML
2231 function recentChangesBlock ()
2232 {
2233 global $wgStylePath ;
2234 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2235 $blockOut = '';
2236 foreach ( $this->rc_cache AS $secureName => $block ) {
2237 if ( count ( $block ) < 2 ) {
2238 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2239 } else {
2240 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2241 }
2242 }
2243
2244 return '<div>'.$blockOut.'</div>' ;
2245 }
2246
2247 # Called in a loop over all displayed RC entries
2248 # Either returns the line, or caches it for later use
2249 function recentChangesLine( &$rc, $watched = false )
2250 {
2251 global $wgUser ;
2252 $usenew = $wgUser->getOption( 'usenewrc' );
2253 if ( $usenew )
2254 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2255 else
2256 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2257 return $line ;
2258 }
2259
2260 function recentChangesLineOld( &$rc, $watched = false )
2261 {
2262 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2263
2264 # Extract DB fields into local scope
2265 extract( $rc->mAttribs );
2266 $curIdEq = 'curid=' . $rc_cur_id;
2267
2268 # Make date header if necessary
2269 $date = $wgLang->date( $rc_timestamp, true);
2270 $s = '';
2271 if ( $date != $this->lastdate ) {
2272 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2273 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2274 $this->lastdate = $date;
2275 $this->rclistOpen = true;
2276 }
2277
2278 # If this edit has not yet been patrolled, make it stick out
2279 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
2280
2281 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2282 # Diff
2283 $s .= '(' . wfMsg( 'diff' ) . ') (';
2284 # Hist
2285 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2286 ') . . ';
2287
2288 # "[[x]] moved to [[y]]"
2289 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2290 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2291 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2292 } else {
2293 # Diff link
2294 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2295 $diffLink = wfMsg( 'diff' );
2296 } else {
2297 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2298 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2299 $rcidparam = "&rcid={$rc_id}";
2300 else
2301 $rcidparam = "";
2302 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2303 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2304 '', '', ' tabindex="'.$rc->counter.'"');
2305 }
2306 $s .= '('.$diffLink.') (';
2307
2308 # History link
2309 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2310 $s .= ') . . ';
2311
2312 # M and N (minor and new)
2313 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2314 if ( $rc_type == RC_NEW ) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2315
2316 # Article link
2317 # If it's a new article, there is no diff link, but if it hasn't been
2318 # patrolled yet, we need to give users a way to do so
2319 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2320 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2321 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2322 else
2323 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2324
2325 if ( $watched ) {
2326 $articleLink = '<strong>'.$articleLink.'</strong>';
2327 }
2328 $s .= ' '.$articleLink;
2329
2330 }
2331
2332 # Timestamp
2333 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2334
2335 # User link (or contributions for unregistered users)
2336 if ( 0 == $rc_user ) {
2337 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2338 $rc_user_text, 'target=' . $rc_user_text );
2339 } else {
2340 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2341 }
2342 $s .= $userLink;
2343
2344 # User talk link
2345 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2346 global $wgDisableAnonTalk;
2347 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2348 $userTalkLink = '';
2349 } else {
2350 $utns=$wgLang->getNsText(NS_USER_TALK);
2351 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2352 }
2353 # Block link
2354 $blockLink='';
2355 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2356 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2357 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2358
2359 }
2360 if($blockLink) {
2361 if($userTalkLink) $userTalkLink .= ' | ';
2362 $userTalkLink .= $blockLink;
2363 }
2364 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2365
2366 # Add comment
2367 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2368 $rc_comment=$this->formatComment($rc_comment);
2369 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2370 }
2371 $s .= "</li>\n";
2372
2373 return $s;
2374 }
2375
2376 function recentChangesLineNew( &$baseRC, $watched = false )
2377 {
2378 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2379
2380 # Create a specialised object
2381 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2382
2383 # Extract fields from DB into the function scope (rc_xxxx variables)
2384 extract( $rc->mAttribs );
2385 $curIdEq = 'curid=' . $rc_cur_id;
2386
2387 # If it's a new day, add the headline and flush the cache
2388 $date = $wgLang->date( $rc_timestamp, true);
2389 $ret = '';
2390 if ( $date != $this->lastdate ) {
2391 # Process current cache
2392 $ret = $this->recentChangesBlock () ;
2393 $this->rc_cache = array() ;
2394 $ret .= "<h4>{$date}</h4>\n";
2395 $this->lastdate = $date;
2396 }
2397
2398 # Make article link
2399 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2400 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2401 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2402 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2403 } else {
2404 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2405 }
2406
2407 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2408 $rc->watched = $watched ;
2409 $rc->link = $clink ;
2410 $rc->timestamp = $time;
2411
2412 # Make "cur" and "diff" links
2413 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2414 $curLink = wfMsg( 'cur' );
2415 $diffLink = wfMsg( 'diff' );
2416 } else {
2417 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2418 $aprops = ' tabindex="'.$baseRC->counter.'"';
2419 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2420 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2421 }
2422
2423 # Make "last" link
2424 $titleObj = $rc->getTitle();
2425 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2426 $lastLink = wfMsg( 'last' );
2427 } else {
2428 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2429 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2430 }
2431
2432 # Make user link (or user contributions for unregistered users)
2433 if ( $rc_user == 0 ) {
2434 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2435 $rc_user_text, 'target=' . $rc_user_text );
2436 } else {
2437 $userLink = $this->makeLink( $wgLang->getNsText(
2438 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2439 }
2440
2441 $rc->userlink = $userLink;
2442 $rc->lastlink = $lastLink;
2443 $rc->curlink = $curLink;
2444 $rc->difflink = $diffLink;
2445
2446 # Make user talk link
2447 $utns=$wgLang->getNsText(NS_USER_TALK);
2448 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2449 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2450
2451 global $wgDisableAnonTalk;
2452 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2453 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2454 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2455 if( $wgDisableAnonTalk )
2456 $rc->usertalklink = ' ('.$blockLink.')';
2457 else
2458 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2459 } else {
2460 if( $wgDisableAnonTalk && ($rc_user == 0) )
2461 $rc->usertalklink = '';
2462 else
2463 $rc->usertalklink = ' ('.$userTalkLink.')';
2464 }
2465
2466 # Put accumulated information into the cache, for later display
2467 # Page moves go on their own line
2468 $title = $rc->getTitle();
2469 $secureName = $title->getPrefixedDBkey();
2470 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2471 # Use an @ character to prevent collision with page names
2472 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2473 } else {
2474 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2475 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2476 }
2477 return $ret;
2478 }
2479
2480 function endImageHistoryList()
2481 {
2482 $s = "</ul>\n";
2483 return $s;
2484 }
2485
2486 /* This function is called by all recent changes variants, by the page history,
2487 and by the user contributions list. It is responsible for formatting edit
2488 comments. It escapes any HTML in the comment, but adds some CSS to format
2489 auto-generated comments (from section editing) and formats [[wikilinks]].
2490 Main author: Erik Möller (moeller@scireview.de)
2491 */
2492 function formatComment($comment)
2493 {
2494 global $wgLang;
2495 $comment=wfEscapeHTML($comment);
2496
2497 # The pattern for autogen comments is / * foo * /, which makes for
2498 # some nasty regex.
2499 # We look for all comments, match any text before and after the comment,
2500 # add a separator where needed and format the comment itself with CSS
2501 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2502 $pre=$match[1];
2503 $auto=$match[2];
2504 $post=$match[3];
2505 $sep='-';
2506 if($pre) { $auto = $sep.' '.$auto; }
2507 if($post) { $auto .= ' '.$sep; }
2508 $auto='<span class="autocomment">'.$auto.'</span>';
2509 $comment=$pre.$auto.$post;
2510 }
2511
2512 # format regular and media links - all other wiki formatting
2513 # is ignored
2514 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2515 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2516 # Handle link renaming [[foo|text]] will show link as "text"
2517 if( "" != $match[3] ) {
2518 $text = $match[3];
2519 } else {
2520 $text = $match[1];
2521 }
2522 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2523 # Media link; trail not supported.
2524 $linkRegexp = '/\[\[(.*?)\]\]/';
2525 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2526 } else {
2527 # Other kind of link
2528 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2529 $trail = $submatch[1];
2530 } else {
2531 $trail = "";
2532 }
2533 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2534 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2535 }
2536 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2537 }
2538 return $comment;
2539 }
2540
2541 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2542 {
2543 global $wgUser, $wgLang, $wgTitle;
2544
2545 $datetime = $wgLang->timeanddate( $timestamp, true );
2546 $del = wfMsg( 'deleteimg' );
2547 $delall = wfMsg( 'deleteimgcompletely' );
2548 $cur = wfMsg( 'cur' );
2549
2550 if ( $iscur ) {
2551 $url = Image::wfImageUrl( $img );
2552 $rlink = $cur;
2553 if ( $wgUser->isSysop() ) {
2554 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2555 '&action=delete' );
2556 $style = $this->getInternalLinkAttributes( $link, $delall );
2557
2558 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2559 } else {
2560 $dlink = $del;
2561 }
2562 } else {
2563 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2564 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2565 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2566 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2567 urlencode( $img ) );
2568 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2569 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2570 } else {
2571 # Having live active links for non-logged in users
2572 # means that bots and spiders crawling our site can
2573 # inadvertently change content. Baaaad idea.
2574 $rlink = wfMsg( 'revertimg' );
2575 $dlink = $del;
2576 }
2577 }
2578 if ( 0 == $user ) {
2579 $userlink = $usertext;
2580 } else {
2581 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2582 ':'.$usertext, $usertext );
2583 }
2584 $nbytes = wfMsg( 'nbytes', $size );
2585 $style = $this->getInternalLinkAttributes( $url, $datetime );
2586
2587 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2588 . " . . {$userlink} ({$nbytes})";
2589
2590 if ( '' != $description && '*' != $description ) {
2591 $sk=$wgUser->getSkin();
2592 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2593 }
2594 $s .= "</li>\n";
2595 return $s;
2596 }
2597
2598 function tocIndent($level) {
2599 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2600 }
2601
2602 function tocUnindent($level) {
2603 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2604 }
2605
2606 # parameter level defines if we are on an indentation level
2607 function tocLine( $anchor, $tocline, $level ) {
2608 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2609 if($level) {
2610 return $link."\n";
2611 } else {
2612 return '<div class="tocline">'.$link."</div>\n";
2613 }
2614
2615 }
2616
2617 function tocTable($toc) {
2618 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2619 # try min-width & co when somebody gets a chance
2620 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2621 return
2622 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2623 '<b>'.wfMsg('toc').'</b>' .
2624 $hideline .
2625 '</td></tr><tr id="tocinside"><td>'."\n".
2626 $toc."</td></tr></table>\n";
2627 }
2628
2629 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2630 function editSectionScript( $section, $head ) {
2631 global $wgTitle, $wgRequest;
2632 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2633 return $head;
2634 }
2635 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2636 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2637 }
2638
2639 function editSectionLink( $section ) {
2640 global $wgRequest;
2641 global $wgTitle, $wgUser, $wgLang;
2642
2643 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2644 # Section edit links would be out of sync on an old page.
2645 # But, if we're diffing to the current page, they'll be
2646 # correct.
2647 return '';
2648 }
2649
2650 $editurl = '&section='.$section;
2651 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2652
2653 if( $wgLang->isRTL() ) {
2654 $farside = 'left';
2655 $nearside = 'right';
2656 } else {
2657 $farside = 'right';
2658 $nearside = 'left';
2659 }
2660 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2661
2662 }
2663
2664 // This function is called by EditPage.php and shows a bulletin board style
2665 // toolbar for common editing functions. It can be disabled in the user preferences.
2666 // The necsesary JavaScript code can be found in style/wikibits.js.
2667 function getEditToolbar() {
2668 global $wgStylePath, $wgLang, $wgMimeType;
2669
2670 // toolarray an array of arrays which each include the filename of
2671 // the button image (without path), the opening tag, the closing tag,
2672 // and optionally a sample text that is inserted between the two when no
2673 // selection is highlighted.
2674 // The tip text is shown when the user moves the mouse over the button.
2675
2676 // Already here are accesskeys (key), which are not used yet until someone
2677 // can figure out a way to make them work in IE. However, we should make
2678 // sure these keys are not defined on the edit page.
2679 $toolarray=array(
2680 array( 'image'=>'button_bold.png',
2681 'open'=>"\'\'\'",
2682 'close'=>"\'\'\'",
2683 'sample'=>wfMsg('bold_sample'),
2684 'tip'=>wfMsg('bold_tip'),
2685 'key'=>'B'
2686 ),
2687 array( "image"=>"button_italic.png",
2688 "open"=>"\'\'",
2689 "close"=>"\'\'",
2690 "sample"=>wfMsg("italic_sample"),
2691 "tip"=>wfMsg("italic_tip"),
2692 "key"=>"I"
2693 ),
2694 array( "image"=>"button_link.png",
2695 "open"=>"[[",
2696 "close"=>"]]",
2697 "sample"=>wfMsg("link_sample"),
2698 "tip"=>wfMsg("link_tip"),
2699 "key"=>"L"
2700 ),
2701 array( "image"=>"button_extlink.png",
2702 "open"=>"[",
2703 "close"=>"]",
2704 "sample"=>wfMsg("extlink_sample"),
2705 "tip"=>wfMsg("extlink_tip"),
2706 "key"=>"X"
2707 ),
2708 array( "image"=>"button_headline.png",
2709 "open"=>"\\n== ",
2710 "close"=>" ==\\n",
2711 "sample"=>wfMsg("headline_sample"),
2712 "tip"=>wfMsg("headline_tip"),
2713 "key"=>"H"
2714 ),
2715 array( "image"=>"button_image.png",
2716 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2717 "close"=>"]]",
2718 "sample"=>wfMsg("image_sample"),
2719 "tip"=>wfMsg("image_tip"),
2720 "key"=>"D"
2721 ),
2722 array( "image"=>"button_media.png",
2723 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2724 "close"=>"]]",
2725 "sample"=>wfMsg("media_sample"),
2726 "tip"=>wfMsg("media_tip"),
2727 "key"=>"M"
2728 ),
2729 array( "image"=>"button_math.png",
2730 "open"=>"\\<math\\>",
2731 "close"=>"\\</math\\>",
2732 "sample"=>wfMsg("math_sample"),
2733 "tip"=>wfMsg("math_tip"),
2734 "key"=>"C"
2735 ),
2736 array( "image"=>"button_nowiki.png",
2737 "open"=>"\\<nowiki\\>",
2738 "close"=>"\\</nowiki\\>",
2739 "sample"=>wfMsg("nowiki_sample"),
2740 "tip"=>wfMsg("nowiki_tip"),
2741 "key"=>"N"
2742 ),
2743 array( "image"=>"button_sig.png",
2744 "open"=>"--~~~~",
2745 "close"=>"",
2746 "sample"=>"",
2747 "tip"=>wfMsg("sig_tip"),
2748 "key"=>"Y"
2749 ),
2750 array( "image"=>"button_hr.png",
2751 "open"=>"\\n----\\n",
2752 "close"=>"",
2753 "sample"=>"",
2754 "tip"=>wfMsg("hr_tip"),
2755 "key"=>"R"
2756 )
2757 );
2758 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2759
2760 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2761 foreach($toolarray as $tool) {
2762
2763 $image=$wgStylePath.'/images/'.$tool['image'];
2764 $open=$tool['open'];
2765 $close=$tool['close'];
2766 $sample = addslashes( $tool['sample'] );
2767
2768 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2769 // Older browsers show a "speedtip" type message only for ALT.
2770 // Ideally these should be different, realistically they
2771 // probably don't need to be.
2772 $tip = addslashes( $tool['tip'] );
2773
2774 #$key = $tool["key"];
2775
2776 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2777 }
2778
2779 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2780 $toolbar.="document.writeln(\"</div>\");\n";
2781
2782 $toolbar.="/*]]>*/\n</script>";
2783 return $toolbar;
2784 }
2785
2786 }
2787
2788 }
2789 ?>