Manual:Skinning/Example
From MediaWiki.org
The following code is an annotated version of MediaWiki's default MonoBook skin.
The various page elements (e.g. sidebar navigation, page tools etc.) have been extracted and commented accordingly.
Note that the code contains a fix for returning category links as a proper UL element (instead of returning a mostly unordered string, which is the default behavior).
<?php /** * [FooBar] skin * * @version [#].[#].[#] * @author [name] ([URL] / [E-Mail]) * @license [URL] [name] * */ // initialize if( !defined('MEDIAWIKI') ) die("This Skin file is not a valid Entry Point."); require_once('includes/SkinTemplate.php'); // inherit main code from SkinTemplate, set the CSS and template filter class Skin[FooBar] extends SkinTemplate { function initPage(&$out) { SkinTemplate::initPage($out); $this->skinname = '[foobar]'; $this->stylename = '[foobar]'; $this->template = '[FooBar]Template'; } } class [FooBar]Template extends QuickTemplate { /* hijack category functions to create a proper list */ function getCategories() { $catlinks=$this->getCategoryLinks(); if(!empty($catlinks)) { return "<ul id='catlinks'>{$catlinks}</ul>"; } } function getCategoryLinks() { global $wgOut, $wgUser, $wgTitle, $wgUseCategoryBrowser; global $wgContLang; if(count($wgOut->mCategoryLinks) == 0) return ''; $skin = $wgUser->getSkin(); # separator $sep = ""; // use Unicode bidi embedding override characters, // to make sure links don't smash each other up in ugly ways $dir = $wgContLang->isRTL() ? 'rtl' : 'ltr'; $embed = "<li dir='$dir'>"; $pop = '</li>'; $t = $embed . implode ( "{$pop} {$sep} {$embed}" , $wgOut->mCategoryLinks ) . $pop; $msg = wfMsgExt('pagecategories', array('parsemag', 'escape'), count($wgOut->mCategoryLinks)); $s = $skin->makeLinkObj(Title::newFromText(wfMsgForContent('pagecategorieslink')), $msg) . $t; # optional 'dmoz-like' category browser - will be shown under the list # of categories an article belongs to if($wgUseCategoryBrowser) { $s .= '<br /><hr />'; # get a big array of the parents tree $parenttree = $wgTitle->getParentCategoryTree(); # Skin object passed by reference because it can not be # accessed under the method subfunction drawCategoryBrowser $tempout = explode("\n", Skin::drawCategoryBrowser($parenttree, $this)); # clean out bogus first entry and sort them unset($tempout[0]); asort($tempout); # output one per line $s .= implode("<br />\n", $tempout); } return $s; } /** * Template filter callback for this skin. * Takes an associative array of data set from a SkinTemplate-based * class, and a wrapper for MediaWiki's localization database, and * outputs a formatted page. * * @access private */ function execute() { global $wgUser, $wgSitename; $skin = $wgUser->getSkin(); // retrieve site name $this->set('sitename', $wgSitename); // suppress warnings to prevent notices about missing indexes in $this->data wfSuppressWarnings(); // use hijacked category functions $this->set('catlinks', $this->getCategories()); /* compose XHTML output */ ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="<?php $this->text('xhtmldefaultnamespace') ?>" <?php foreach($this->data['xhtmlnamespaces'] as $tag => $ns) { ?>xmlns:<?php echo "{$tag}=\"{$ns}\" "; } ?>xml:lang="<?php $this->text('lang') ?>" lang="<?php $this->text('lang') ?>" dir="<?php $this->text('dir') ?>"> <head> <meta http-equiv="Content-Type" content="<?php $this->text('mimetype') ?>; charset=<?php $this->text('charset') ?>" /> <?php $this->html('headlinks') ?> <title><?php $this->text('pagetitle') ?></title> <?php /*** general style sheets ***/ ?> <style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/main.css?<?php echo $GLOBALS['wgStyleVersion'] ?>"; @import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/contents.css?<?php echo $GLOBALS['wgStyleVersion'] ?>"; /*]]>*/</style> <?php /*** media-specific style sheets ***/ ?> <link rel="stylesheet" type="text/css" <?php if(empty($this->data['printable']) ) { ?>media="print"<?php } ?> href="<?php $this->text('stylepath') ?>/common/commonPrint.css?<?php echo $GLOBALS['wgStyleVersion'] ?>" /> <link rel="stylesheet" type="text/css" media="handheld" href="<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/handheld.css?<?php echo $GLOBALS['wgStyleVersion'] ?>" /> <?php /*** browser-specific style sheets ***/ ?> <!--[if lt IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE50Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]--> <!--[if IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE55Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]--> <!--[if IE 6]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE60Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]--> <!--[if IE 7]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE70Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]--> <?php /*** general IE fixes ***/ ?> <!--[if lt IE 7]> <script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath') ?>/common/IEFixes.js?<?php echo $GLOBALS['wgStyleVersion'] ?>"></script> <meta http-equiv="imagetoolbar" content="no" /> <![endif]--> <?php print Skin::makeGlobalVariablesScript($this->data); ?> <?php /*** various MediaWiki-related scripts and styles ***/ ?> <script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath') ?>/common/wikibits.js?<?php echo $GLOBALS['wgStyleVersion'] ?>"><!-- wikibits js --></script> <?php if($this->data['jsvarurl']) { ?> <script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('jsvarurl') ?>"><!-- site js --></script> <?php } ?> <?php if($this->data['pagecss']) { ?> <style type="text/css"><?php $this->html('pagecss') ?></style> <?php } if($this->data['usercss']) { ?> <style type="text/css"><?php $this->html('usercss') ?></style> <?php } if($this->data['userjs']) { ?> <script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('userjs' ) ?>"></script> <?php } if($this->data['userjsprev']) { ?> <script type="<?php $this->text('jsmimetype') ?>"><?php $this->html('userjsprev') ?></script> <?php } if($this->data['trackbackhtml']) print $this->data['trackbackhtml']; ?> <!-- Head Scripts --> <?php $this->html('headscripts') ?> </head> <!-- Body --> <body <?php if($this->data['body_ondblclick']) { ?>ondblclick="<?php $this->text('body_ondblclick') ?>"<?php } ?> <?php if($this->data['body_onload']) { ?>onload="<?php $this->text('body_onload') ?>"<?php } ?> class="mediawiki <?php $this->text('nsclass') ?> <?php $this->text('dir') ?> <?php $this->text('pageclass') ?>"> <!-- Site Name --> <?php echo $this->text('sitename') ?> <!-- Logo Image --> <div class="portlet" id="p-logo"> <a style="background-image: url(<?php $this->text('logopath') ?>);" <?php ?>href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href'])?>"<?php echo $skin->tooltipAndAccesskey('n-mainpage') ?>></a> </div> <script type="<?php $this->text('jsmimetype') ?>"> if (window.isMSIE55) fixalpha(); </script> <!-- IE alpha-transparency fix --> <!-- Tagline (Site Subtitle) --> <h3 id="siteSub"><?php $this->msg('tagline') ?></h3> <!-- Site Notice [conditional] --> <?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?> <!-- User-Messages Notification [conditional] --> <?php if($this->data['newtalk']) { ?><div class="usermessage"><?php $this->html('newtalk') ?></div><?php } ?> <!-- User Toolbar [iterative] --> <div class="portlet" id="p-personal"> <h5><?php $this->msg('personaltools') ?></h5> <!-- User Toolbar Label/Caption [optional] --> <div class="pBody"> <ul> <?php foreach($this->data['personal_urls'] as $key => $item) { ?> <li id="pt-<?php echo Sanitizer::escapeId($key) ?>"<?php if ($item['active']) { ?> class="active"<?php } ?>><a href="<?php echo htmlspecialchars($item['href']) ?>"<?php echo $skin->tooltipAndAccesskey('pt-'.$key) ?><?php if(!empty($item['class'])) { ?> class="<?php echo htmlspecialchars($item['class']) ?>"<?php } ?>><?php echo htmlspecialchars($item['text']) ?></a></li> <?php } ?> </ul> </div> </div> <!-- Jump-To Links (intra-page navigation) [conditional] [optional] --> <?php if($this->data['showjumplinks']) { ?><div id="jump-to-nav"><?php $this->msg('jumpto') ?> <a href="#column-one"><?php $this->msg('jumptonavigation') ?></a>, <a href="#searchInput"><?php $this->msg('jumptosearch') ?></a></div><?php } ?> <!-- Search Box --> <div id="p-search" class="portlet"> <h5><label for="searchInput"><?php $this->msg('search') ?></label></h5> <div id="searchBody" class="pBody"> <form action="<?php $this->text('searchaction') ?>" id="searchform"><div> <input id="searchInput" name="search" type="text"<?php echo $skin->tooltipAndAccesskey('search'); if( isset( $this->data['search'] ) ) { ?> value="<?php $this->text('search') ?>"<?php } ?> /> <input type='submit' name="go" class="searchButton" id="searchGoButton" value="<?php $this->msg('searcharticle') ?>" /> <input type='submit' name="fulltext" class="searchButton" id="mw-searchButton" value="<?php $this->msg('searchbutton') ?>" /> </div></form> </div> </div> <!-- Sidebar Navigation [iterative] --> <?php foreach ($this->data['sidebar'] as $bar => $cont) { ?> <div class='portlet' id='p-<?php echo Sanitizer::escapeId($bar) ?>'<?php echo $skin->tooltip('p-'.$bar) ?>> <h5><?php $out = wfMsg( $bar ); if (wfEmptyMsg($bar, $out)) echo $bar; else echo $out; ?></h5> <div class='pBody'> <ul> <?php foreach($cont as $key => $val) { ?> <li id="<?php echo Sanitizer::escapeId($val['id']) ?>"<?php if ( $val['active'] ) { ?> class="active" <?php } ?>><a href="<?php echo htmlspecialchars($val['href']) ?>"<?php echo $skin->tooltipAndAccesskey($val['id']) ?>><?php echo htmlspecialchars($val['text']) ?></a></li> <?php } ?> </ul> </div> </div> <?php } ?> <!-- Toolbox --> <div class="portlet" id="p-tb"> <h5><?php $this->msg('toolbox') ?></h5> <div class="pBody"> <ul> <?php if($this->data['notspecialpage']) { ?> <li id="t-whatlinkshere"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['whatlinkshere']['href']) ?>"<?php echo $skin->tooltipAndAccesskey('t-whatlinkshere') ?>><?php $this->msg('whatlinkshere') ?></a></li> <?php if( $this->data['nav_urls']['recentchangeslinked'] ) { ?> <li id="t-recentchangeslinked"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['recentchangeslinked']['href']) ?>"<?php echo $skin->tooltipAndAccesskey('t-recentchangeslinked') ?>><?php $this->msg('recentchangeslinked') ?></a></li> <?php } } if(isset($this->data['nav_urls']['trackbacklink'])) { ?> <li id="t-trackbacklink"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['trackbacklink']['href']) ?>"<?php echo $skin->tooltipAndAccesskey('t-trackbacklink') ?>><?php $this->msg('trackbacklink') ?></a></li> <?php } if($this->data['feeds']) { ?> <li id="feedlinks"><?php foreach($this->data['feeds'] as $key => $feed) { ?><span id="feed-<?php echo Sanitizer::escapeId($key) ?>"><a href="<?php echo htmlspecialchars($feed['href']) ?>"<?php echo $skin->tooltipAndAccesskey('feed-'.$key) ?>><?php echo htmlspecialchars($feed['text'])?></a> </span> <?php } ?></li><?php } foreach( array('contributions', 'blockip', 'emailuser', 'upload', 'specialpages') as $special ) { if($this->data['nav_urls'][$special]) { ?><li id="t-<?php echo $special ?>"><a href="<?php echo htmlspecialchars($this->data['nav_urls'][$special]['href']) ?>"<?php echo $skin->tooltipAndAccesskey('t-'.$special) ?>><?php $this->msg($special) ?></a></li> <?php } } if(!empty($this->data['nav_urls']['print']['href'])) { ?> <li id="t-print"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['print']['href']) ?>"<?php echo $skin->tooltipAndAccesskey('t-print') ?>><?php $this->msg('printableversion') ?></a></li><?php } if(!empty($this->data['nav_urls']['permalink']['href'])) { ?> <li id="t-permalink"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['permalink']['href']) ?>"<?php echo $skin->tooltipAndAccesskey('t-permalink') ?>><?php $this->msg('permalink') ?></a></li><?php } elseif ($this->data['nav_urls']['permalink']['href'] === '') { ?> <li id="t-ispermalink"<?php echo $skin->tooltip('t-ispermalink') ?>><?php $this->msg('permalink') ?></li><?php } wfRunHooks( 'MonoBookTemplateToolboxEnd', array( &$this ) ); ?> </ul> </div> </div> <!-- Language Links --> <?php if( $this->data['language_urls'] ) { ?> <div id="p-lang" class="portlet"> <h5><?php $this->msg('otherlanguages') ?></h5> <div class="pBody"> <ul> <?php foreach($this->data['language_urls'] as $langlink) { ?> <li class="<?php echo htmlspecialchars($langlink['class'])?>"><?php ?><a href="<?php echo htmlspecialchars($langlink['href']) ?>"><?php echo $langlink['text'] ?></a></li> <?php } ?> </ul> </div> </div> <?php } ?> <!-- Page Name --> <h1 class="firstHeading"><?php $this->data['displaytitle']!=""?$this->html('title'):$this->text('title') ?></h1> <!-- Page Subtitle (e.g. redirect notice) --> <div id="contentSub"><?php $this->html('subtitle') ?></div> <!-- Undelete Notice [conditional] --> <?php if($this->data['undelete']) { ?><div id="contentSub2"><?php $this->html('undelete') ?></div><?php } ?> <!-- Page Contents --> <?php $this->html('bodytext') ?> <!-- Category Links [conditional] --> <?php if($this->data['catlinks']) { ?><div id="catlinks"><?php $this->html('catlinks') ?></div><?php } ?> <!-- Page Toolbar [iterative] --> <div id="p-cactions" class="portlet"> <h5><?php $this->msg('views') ?></h5> <!-- Page Toolbar Label/Caption [optional] --> <div class="pBody"> <ul> <?php foreach($this->data['content_actions'] as $key => $tab) { ?> <li id="ca-<?php echo Sanitizer::escapeId($key) ?>"<?php if($tab['class']) { ?> class="<?php echo htmlspecialchars($tab['class']) ?>"<?php } ?>><a href="<?php echo htmlspecialchars($tab['href']) ?>"<?php echo $skin->tooltipAndAccesskey('ca-'.$key) ?>><?php echo htmlspecialchars($tab['text']) ?></a></li> <?php } ?> </ul> </div> </div> <!-- Footer --> <div id="footer"> <?php if($this->data['poweredbyico']) { ?> <div id="f-poweredbyico"><?php $this->html('poweredbyico') ?></div> <?php } if($this->data['copyrightico']) { ?> <div id="f-copyrightico"><?php $this->html('copyrightico') ?></div> <?php } // Generate additional footer links ?> <ul id="f-list"> <?php $footerlinks = array( 'lastmod', 'viewcount', 'numberofwatchingusers', 'credits', 'copyright', 'privacy', 'about', 'disclaimer', 'tagline', ); foreach( $footerlinks as $aLink ) { if( isset( $this->data[$aLink] ) && $this->data[$aLink] ) { ?> <li id="<?php echo$aLink?>"><?php $this->html($aLink) ?></li> <?php } } ?> </ul> </div> <!-- scripts and debugging information --> <?php $this->html('bottomscripts'); /* JS call to runBodyOnloadHook */ ?> <?php $this->html('reporttime') ?> <?php if ( $this->data['debug'] ): ?> <!-- Debug output: <?php $this->text( 'debug' ); ?> --> <?php endif; ?> </body> </html> <?php wfRestoreWarnings(); } // end of execute() method } // end of class ?>