Add wfSuppressWarnings(); to CologneBlue.
[lhc/web/wiklou.git] / skins / CologneBlue.php
1 <?php
2 /**
3 * Cologne Blue: A nicer-looking alternative to Standard.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @todo document
21 * @file
22 * @ingroup Skins
23 */
24
25 if( !defined( 'MEDIAWIKI' ) ) {
26 die( -1 );
27 }
28
29 /**
30 * @todo document
31 * @ingroup Skins
32 */
33 class SkinCologneBlue extends SkinTemplate {
34 var $skinname = 'cologneblue', $stylename = 'cologneblue',
35 $template = 'CologneBlueTemplate';
36 var $useHeadElement = true;
37
38 /**
39 * @param $out OutputPage
40 */
41 function setupSkinUserCss( OutputPage $out ){
42 $out->addModuleStyles( 'mediawiki.legacy.shared' );
43 $out->addModuleStyles( 'mediawiki.legacy.oldshared' );
44 $out->addModuleStyles( 'skins.cologneblue' );
45 }
46
47 /**
48 * Override langlink formatting behavior not to uppercase the language names.
49 * See otherLanguages() in CologneBlueTemplate.
50 */
51 function formatLanguageName( $name ) {
52 return $name;
53 }
54 }
55
56 class CologneBlueTemplate extends BaseTemplate {
57 function execute() {
58 // Suppress warnings to prevent notices about missing indexes in $this->data
59 wfSuppressWarnings();
60 $this->html( 'headelement' );
61 echo $this->beforeContent();
62 $this->html( 'bodytext' );
63 echo "\n";
64 echo $this->afterContent();
65 $this->html( 'dataAfterContent' );
66 $this->printTrail();
67 echo "\n</body></html>";
68 wfRestoreWarnings();
69 }
70
71
72 /**
73 * Language/charset variant links for classic-style skins
74 * @return string
75 *
76 * @fixed
77 */
78 function variantLinks() {
79 $s = array();
80
81 $variants = $this->data['content_navigation']['variants'];
82
83 foreach ( $variants as $key => $link ) {
84 $s[] = $this->makeListItem( $key, $link, array( 'tag' => 'span' ) );
85 }
86
87 return $this->getSkin()->getLanguage()->pipeList( $s );
88 }
89
90 // @fixed
91 function otherLanguages() {
92 global $wgHideInterlanguageLinks;
93 if ( $wgHideInterlanguageLinks ) {
94 return "";
95 }
96
97 // We override SkinTemplate->formatLanguageName() in SkinCologneBlue
98 // not to capitalize the language names.
99 $language_urls = $this->data['language_urls'];
100 if ( empty( $language_urls ) ) {
101 return "";
102 }
103
104 $s = array();
105 foreach ( $language_urls as $key => $data ) {
106 $s[] = $this->makeListItem( $key, $data, array( 'tag' => 'span' ) );
107 }
108
109 return wfMessage( 'otherlanguages' )->text()
110 . wfMessage( 'colon-separator' )->text()
111 . $this->getSkin()->getLanguage()->pipeList( $s );
112 }
113
114 // @fixed
115 function pageTitleLinks() {
116 $s = array();
117 $footlinks = $this->getFooterLinks();
118
119 foreach ( $footlinks['places'] as $item ) {
120 $s[] = $this->data[$item];
121 }
122
123 return $this->getSkin()->getLanguage()->pipeList( $s );
124 }
125
126 function bottomLinks() {
127 $sep = wfMessage( 'pipe-separator' )->escaped() . "\n";
128
129 $s = '';
130 if ( $this->getSkin()->getOutput()->isArticleRelated() ) {
131 $element[] = '<strong>' . $this->editThisPage() . '</strong>';
132
133 if ( $this->getSkin()->getUser()->isLoggedIn() ) {
134 $element[] = $this->watchThisPage();
135 }
136
137 $element[] = $this->talkLink();
138 $element[] = $this->historyLink();
139 $element[] = $this->whatLinksHere();
140 $element[] = $this->watchPageLinksLink();
141
142 $title = $this->getSkin()->getTitle();
143
144 if (
145 $title->getNamespace() == NS_USER ||
146 $title->getNamespace() == NS_USER_TALK
147 ) {
148 $id = User::idFromName( $title->getText() );
149 $ip = User::isIP( $title->getText() );
150
151 # Both anons and non-anons have contributions list
152 if ( $id || $ip ) {
153 $element[] = $this->userContribsLink();
154 }
155
156 if ( $this->getSkin()->showEmailUser( $id ) ) {
157 $element[] = $this->emailUserLink();
158 }
159 }
160
161 $s = implode( $element, $sep );
162
163 if ( $title->getArticleID() ) {
164 $s .= "\n<br />";
165
166 // Delete/protect/move links for privileged users
167 if ( $this->getSkin()->getUser()->isAllowed( 'delete' ) ) {
168 $s .= $this->deleteThisPage();
169 }
170
171 if ( $this->getSkin()->getUser()->isAllowed( 'protect' ) ) {
172 $s .= $sep . $this->protectThisPage();
173 }
174
175 if ( $this->getSkin()->getUser()->isAllowed( 'move' ) ) {
176 $s .= $sep . $this->moveThisPage();
177 }
178 }
179
180 $s .= "<br />\n" . $this->otherLanguages();
181 }
182
183 return $s;
184 }
185
186 function editThisPage() {
187 if ( !$this->getSkin()->getOutput()->isArticleRelated() ) {
188 $s = wfMessage( 'protectedpage' )->text();
189 } else {
190 $title = $this->getSkin()->getTitle();
191 if ( $title->quickUserCan( 'edit' ) && $title->exists() ) {
192 $t = wfMessage( 'editthispage' )->text();
193 } elseif ( $title->quickUserCan( 'create' ) && !$title->exists() ) {
194 $t = wfMessage( 'create-this-page' )->text();
195 } else {
196 $t = wfMessage( 'viewsource' )->text();
197 }
198
199 $s = Linker::linkKnown(
200 $title,
201 $t,
202 array(),
203 $this->getSkin()->editUrlOptions()
204 );
205 }
206
207 return $s;
208 }
209
210 function deleteThisPage() {
211 $diff = $this->getSkin()->getRequest()->getVal( 'diff' );
212 $title = $this->getSkin()->getTitle();
213
214 if ( $title->getArticleID() && ( !$diff ) && $this->getSkin()->getUser()->isAllowed( 'delete' ) ) {
215 $t = wfMessage( 'deletethispage' )->text();
216
217 $s = Linker::linkKnown(
218 $title,
219 $t,
220 array(),
221 array( 'action' => 'delete' )
222 );
223 } else {
224 $s = '';
225 }
226
227 return $s;
228 }
229
230 function protectThisPage() {
231 $diff = $this->getSkin()->getRequest()->getVal( 'diff' );
232 $title = $this->getSkin()->getTitle();
233
234 if ( $title->getArticleID() && ( ! $diff ) && $this->getSkin()->getUser()->isAllowed( 'protect' ) ) {
235 if ( $title->isProtected() ) {
236 $text = wfMessage( 'unprotectthispage' )->text();
237 $query = array( 'action' => 'unprotect' );
238 } else {
239 $text = wfMessage( 'protectthispage' )->text();
240 $query = array( 'action' => 'protect' );
241 }
242
243 $s = Linker::linkKnown(
244 $title,
245 $text,
246 array(),
247 $query
248 );
249 } else {
250 $s = '';
251 }
252
253 return $s;
254 }
255
256 function watchThisPage() {
257 // Cache
258 $title = $this->getSkin()->getTitle();
259
260 if ( $this->getSkin()->getOutput()->isArticleRelated() ) {
261 if ( $this->getSkin()->getUser()->isWatched( $title ) ) {
262 $text = wfMessage( 'unwatchthispage' )->text();
263 $query = array(
264 'action' => 'unwatch',
265 'token' => UnwatchAction::getUnwatchToken( $title, $this->getSkin()->getUser() ),
266 );
267 $id = 'mw-unwatch-link';
268 } else {
269 $text = wfMessage( 'watchthispage' )->text();
270 $query = array(
271 'action' => 'watch',
272 'token' => WatchAction::getWatchToken( $title, $this->getSkin()->getUser() ),
273 );
274 $id = 'mw-watch-link';
275 }
276
277 $s = Linker::linkKnown(
278 $title,
279 $text,
280 array( 'id' => $id ),
281 $query
282 );
283 } else {
284 $s = wfMessage( 'notanarticle' )->text();
285 }
286
287 return $s;
288 }
289
290 function moveThisPage() {
291 if ( $this->getSkin()->getTitle()->quickUserCan( 'move' ) ) {
292 return Linker::linkKnown(
293 SpecialPage::getTitleFor( 'Movepage' ),
294 wfMessage( 'movethispage' )->text(),
295 array(),
296 array( 'target' => $this->getSkin()->getTitle()->getPrefixedDBkey() )
297 );
298 } else {
299 // no message if page is protected - would be redundant
300 return '';
301 }
302 }
303
304 function historyLink() {
305 return Linker::link(
306 $this->getSkin()->getTitle(),
307 wfMessage( 'history' )->escaped(),
308 array( 'rel' => 'archives' ),
309 array( 'action' => 'history' )
310 );
311 }
312
313 function whatLinksHere() {
314 return Linker::linkKnown(
315 SpecialPage::getTitleFor( 'Whatlinkshere', $this->getSkin()->getTitle()->getPrefixedDBkey() ),
316 wfMessage( 'whatlinkshere' )->escaped()
317 );
318 }
319
320 function userContribsLink() {
321 return Linker::linkKnown(
322 SpecialPage::getTitleFor( 'Contributions', $this->getSkin()->getTitle()->getDBkey() ),
323 wfMessage( 'contributions' )->escaped()
324 );
325 }
326
327 function emailUserLink() {
328 return Linker::linkKnown(
329 SpecialPage::getTitleFor( 'Emailuser', $this->getSkin()->getTitle()->getDBkey() ),
330 wfMessage( 'emailuser' )->escaped()
331 );
332 }
333
334 function watchPageLinksLink() {
335 if ( !$this->getSkin()->getOutput()->isArticleRelated() ) {
336 return wfMessage( 'parentheses', wfMessage( 'notanarticle' )->text() )->escaped();
337 } else {
338 return Linker::linkKnown(
339 SpecialPage::getTitleFor( 'Recentchangeslinked', $this->getSkin()->getTitle()->getPrefixedDBkey() ),
340 wfMessage( 'recentchangeslinked-toolbox' )->escaped()
341 );
342 }
343 }
344
345 function talkLink() {
346 $title = $this->getSkin()->getTitle();
347 if ( NS_SPECIAL == $title->getNamespace() ) {
348 # No discussion links for special pages
349 return '';
350 }
351
352 $linkOptions = array();
353
354 if ( $title->isTalkPage() ) {
355 $link = $title->getSubjectPage();
356 switch( $link->getNamespace() ) {
357 case NS_MAIN:
358 $text = wfMessage( 'articlepage' );
359 break;
360 case NS_USER:
361 $text = wfMessage( 'userpage' );
362 break;
363 case NS_PROJECT:
364 $text = wfMessage( 'projectpage' );
365 break;
366 case NS_FILE:
367 $text = wfMessage( 'imagepage' );
368 # Make link known if image exists, even if the desc. page doesn't.
369 if ( wfFindFile( $link ) )
370 $linkOptions[] = 'known';
371 break;
372 case NS_MEDIAWIKI:
373 $text = wfMessage( 'mediawikipage' );
374 break;
375 case NS_TEMPLATE:
376 $text = wfMessage( 'templatepage' );
377 break;
378 case NS_HELP:
379 $text = wfMessage( 'viewhelppage' );
380 break;
381 case NS_CATEGORY:
382 $text = wfMessage( 'categorypage' );
383 break;
384 default:
385 $text = wfMessage( 'articlepage' );
386 }
387 } else {
388 $link = $title->getTalkPage();
389 $text = wfMessage( 'talkpage' );
390 }
391
392 $s = Linker::link( $link, $text->text(), array(), array(), $linkOptions );
393
394 return $s;
395 }
396
397 /**
398 * @return string
399 *
400 * @fixed
401 */
402 function beforeContent() {
403 ob_start();
404 ?>
405 <div id="content">
406 <div id="topbar">
407 <p id="sitetitle">
408 <a href="<?php echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] ) ?>">
409 <?php echo wfMessage( 'sitetitle' )->escaped() ?>
410 </a>
411 </p>
412 <p id="sitesub"><?php echo wfMessage( 'sitesubtitle' )->escaped() ?></p>
413
414 <div id="toplinks">
415 <p id="syslinks"><?php echo $this->sysLinks() ?></p>
416 <p id="variantlinks"><?php echo $this->variantLinks() ?></p>
417 </div>
418 <div id="linkcollection">
419 <div id="langlinks"><?php echo str_replace( '<br />', '', $this->otherLanguages() ) ?></div>
420 <?php echo $this->getSkin()->getCategories() ?>
421 <div id="titlelinks"><?php echo $this->pageTitleLinks() ?></div>
422 <?php if ( $this->data['newtalk'] ) { ?>
423 <div class="usermessage"><strong><?php echo $this->data['newtalk'] ?></strong></div>
424 <?php } ?>
425 </div>
426 </div>
427 <div id="article">
428 <?php if ( $this->getSkin()->getSiteNotice() ) { ?>
429 <div id="siteNotice"><?php echo $this->getSkin()->getSiteNotice() ?></div>
430 <?php } ?>
431 <h1 id="firstHeading"><span dir="auto"><?php echo $this->data['title'] ?></span></h1>
432 <?php if ( $this->translator->translate( 'tagline' ) ) { ?>
433 <p class="tagline"><?php echo htmlspecialchars( $this->translator->translate( 'tagline' ) ) ?></p>
434 <?php } ?>
435 <?php if ( $this->getSkin()->getOutput()->getSubtitle() ) { ?>
436 <p class="subtitle"><?php echo $this->getSkin()->getOutput()->getSubtitle() ?></p>
437 <?php } ?>
438 <?php if ( $this->getSkin()->subPageSubtitle() ) { ?>
439 <p class="subpages"><?php echo $this->getSkin()->subPageSubtitle() ?></p>
440 <?php } ?>
441 <?php
442 $s = ob_get_contents();
443 ob_end_clean();
444
445 return $s;
446 }
447
448 /**
449 * @return string
450 *
451 * @fixed
452 */
453 function afterContent() {
454 ob_start();
455 ?>
456 </div>
457 <div id='footer'>
458 <?php
459 // Page-related links
460 echo $this->bottomLinks();
461 echo "\n<br />";
462
463 // Footer and second searchbox
464 echo $this->getSkin()->getLanguage()->pipeList( array(
465 $this->getSkin()->mainPageLink(),
466 $this->getSkin()->aboutLink(),
467 $this->searchForm( 'footer' )
468 ) );
469 echo "\n<br />";
470
471 // Standard footer info
472 $footlinks = $this->getFooterLinks();
473 if ( $footlinks['info'] ) {
474 foreach ( $footlinks['info'] as $item ) {
475 echo $this->data[$item] . ' ';
476 }
477 }
478 ?>
479 </div>
480 </div>
481 <?php echo $this->quickBar() ?>
482 <?php
483 $s = ob_get_contents();
484 ob_end_clean();
485
486 return $s;
487 }
488
489 /**
490 * @return string
491 *
492 * @fixed
493 */
494 function sysLinks() {
495 $s = array(
496 $this->getSkin()->mainPageLink(),
497 Linker::linkKnown(
498 Title::newFromText( wfMessage( 'aboutpage' )->inContentLanguage()->text() ),
499 wfMessage( 'about' )->text()
500 ),
501 Linker::linkKnown(
502 Title::newFromText( wfMessage( 'helppage' )->inContentLanguage()->text() ),
503 wfMessage( 'help' )->text()
504 ),
505 Linker::linkKnown(
506 Title::newFromText( wfMessage( 'faqpage' )->inContentLanguage()->text() ),
507 wfMessage( 'faq' )->text()
508 ),
509 );
510
511 $personalUrls = $this->getPersonalTools();
512 foreach ( array ( 'logout', 'createaccount', 'login', 'anonlogin' ) as $key ) {
513 if ( $personalUrls[$key] ) {
514 $s[] = $this->makeListItem( $key, $personalUrls[$key], array( 'tag' => 'span' ) );
515 }
516 }
517
518 return $this->getSkin()->getLanguage()->pipeList( $s );
519 }
520
521
522
523
524 /**
525 * @param $heading string
526 * @return string
527 *
528 * @fixed
529 */
530 function menuHead( $heading ) {
531 return "\n<h6>" . htmlspecialchars( $heading ) . "</h6>";
532 }
533
534 /**
535 * Compute the sidebar
536 * @access private
537 *
538 * @return string
539 *
540 * @fixed
541 */
542 function quickBar(){
543 $s = "\n<div id='quickbar'>";
544
545 $sep = "<br />\n";
546
547 $plain_bar = $this->data['sidebar'];
548 $bar = array();
549
550 // Massage the sidebar
551 // We want to place SEARCH at the beginning and a lot of stuff before TOOLBOX (or at the end, if it's missing)
552 $additions_done = false;
553 while ( !$additions_done ) {
554 $bar = array(); // Empty it out
555
556 // Always display search on top
557 $bar['SEARCH'] = true;
558
559 foreach ( $plain_bar as $heading => $links ) {
560 if ( $heading == 'TOOLBOX' ) {
561 if( $links !== NULL ) {
562 // If this is not a toolbox prosthetic we inserted outselves, fill it out
563 $plain_bar['TOOLBOX'] = $this->getToolbox();
564 }
565
566 // And insert the stuff
567
568 // "This page" and "Edit" menus
569 // We need to do some massaging here... we reuse all of the items, except for $...['views']['view'],
570 // as $...['namespaces']['main'] and $...['namespaces']['talk'] together serve the same purpose.
571 // We also don't use $...['variants'], these are displayed in the top menu.
572 $content_navigation = $this->data['content_navigation'];
573 $qbpageoptions = array_merge(
574 $content_navigation['namespaces'],
575 array(
576 'history' => $content_navigation['views']['history'],
577 'watch' => $content_navigation['actions']['watch'],
578 'unwatch' => $content_navigation['actions']['unwatch'],
579 )
580 );
581 $content_navigation['actions']['watch'] = null;
582 $content_navigation['actions']['unwatch'] = null;
583 $qbedit = array_merge(
584 array(
585 'edit' => $content_navigation['views']['edit'],
586 'addsection' => $content_navigation['views']['addsection'],
587 ),
588 $content_navigation['actions']
589 );
590 $bar['qbedit'] = $qbedit;
591 $bar['qbpageoptions'] = $qbpageoptions;
592
593 // Personal tools ("My pages")
594 $bar['qbmyoptions'] = $this->getPersonalTools();
595 foreach ( array ( 'logout', 'createaccount', 'login', 'anonlogin' ) as $key ) {
596 $bar['qbmyoptions'][$key] = false;
597 }
598
599 $additions_done = true;
600 }
601
602 // Re-insert current heading, unless it's SEARCH
603 if ( $heading != 'SEARCH' ) {
604 $bar[$heading] = $plain_bar[$heading];
605 }
606 }
607
608 // If TOOLBOX is missing, $additions_done is still false
609 if ( !$additions_done ) {
610 $plain_bar['TOOLBOX'] = false;
611 }
612 }
613
614 foreach ( $bar as $heading => $links ) {
615 if ( $heading == 'SEARCH' ) {
616 $s .= $this->menuHead( wfMessage( 'qbfind' )->text() );
617 $s .= $this->searchForm( 'sidebar' );
618 } elseif ( $heading == 'LANGUAGES' ) {
619 // discard these; we display languages below page content
620 } else {
621 if ( $links ) {
622 // Use the navigation heading from standard sidebar as the "browse" section
623 if ( $heading == 'navigation' ) {
624 $heading = 'qbbrowse';
625 }
626 if ( $heading == 'TOOLBOX' ) {
627 $heading = 'toolbox';
628 }
629
630 $headingMsg = wfMessage( $heading );
631 $any_link = false;
632 $t = $this->menuHead( $headingMsg->exists() ? $headingMsg->text() : $heading );
633
634 foreach ( $links as $key => $link ) {
635 // Can be empty due to rampant sidebar massaging we're doing above
636 if ( $link ) {
637 $any_link = true;
638 $t .= $this->makeListItem( $key, $link, array( 'tag' => 'span' ) ) . $sep;
639 }
640 }
641
642 if ( $any_link ) {
643 $s .= $t;
644 }
645 }
646 }
647 }
648
649 $s .= $sep . "\n</div>\n";
650 return $s;
651 }
652
653 /**
654 * @param $label string
655 * @return string
656 *
657 * @fixed
658 */
659 function searchForm( $which ) {
660 global $wgUseTwoButtonsSearchForm;
661
662 $search = $this->getSkin()->getRequest()->getText( 'search' );
663 $action = $this->data['searchaction'];
664 $s = "<form id=\"searchform-" . htmlspecialchars($which) . "\" method=\"get\" class=\"inline\" action=\"$action\">";
665 if( $which == 'footer' ) {
666 $s .= wfMessage( 'qbfind' )->text() . ": ";
667 }
668
669 $s .= "<input type='text' class=\"mw-searchInput\" name=\"search\" size=\"14\" value=\""
670 . htmlspecialchars( substr( $search, 0, 256 ) ) . "\" />"
671 . ($which == 'footer' ? " " : "<br />")
672 . "<input type='submit' class=\"searchButton\" name=\"go\" value=\"" . wfMessage( 'searcharticle' )->escaped() . "\" />";
673
674 if( $wgUseTwoButtonsSearchForm ) {
675 $s .= " <input type='submit' class=\"searchButton\" name=\"fulltext\" value=\"" . wfMessage( 'search' )->escaped() . "\" />\n";
676 } else {
677 $s .= '<div><a href="' . $action . '" rel="search">' . wfMessage( 'powersearch-legend' )->escaped() . "</a></div>\n";
678 }
679
680 $s .= '</form>';
681
682 return $s;
683 }
684 }