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