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