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