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