* Moved SkinTemplate::addStyle() and related stuff to OutputPage so that it can be used non-SkinTemplate skins and avoid duplication with the actual OutputPage::addStyle() (the two functions have the same format).
* Non-SkinTemplate skins now also load their CSS with <link> tags instead of @import.
* Moved SkinTemplate::setupUserCss() to Skin.
* Merged action=raw&gen=(js|css) for SkinTemplate and non-SkinTemplate skins, renamed functions to Skin::generateUserJs() and Skin::generateUserStyleSheet() and dropped a lot of cascading call which is a bit incomprehensible.
var $mSquidMaxage = 0;
var $mRevisionId = null;
+ /**
+ * An array of stylesheet filenames (relative from skins path), with options
+ * for CSS media, IE conditions, and RTL/LTR direction.
+ * For internal use; add settings in the skin via $this->addStyle()
+ */
+ var $styles = array();
+
private $mIndexPolicy = 'index';
private $mFollowPolicy = 'follow';
*/
function setStatusCode( $statusCode ) { $this->mStatusCode = $statusCode; }
- # To add an http-equiv meta tag, precede the name with "http:"
- function addMeta( $name, $val ) { array_push( $this->mMetatags, array( $name, $val ) ); }
+ /**
+ * Add a new <meta> tag
+ * To add an http-equiv meta tag, precede the name with "http:"
+ *
+ * @param $name tag name
+ * @param $val tag value
+ */
+ function addMeta( $name, $val ) {
+ array_push( $this->mMetatags, array( $name, $val ) );
+ }
+
function addKeyword( $text ) { array_push( $this->mKeywords, $text ); }
function addScript( $script ) { $this->mScripts .= "\t\t".$script; }
- function addStyle( $style ) {
- global $wgStylePath, $wgStyleVersion;
- $this->addLink(
- array(
- 'rel' => 'stylesheet',
- 'href' => $wgStylePath . '/' . $style . '?' . $wgStyleVersion,
- 'type' => 'text/css' ) );
- }
function addExtensionStyle( $url ) {
$linkarr = array( 'rel' => 'stylesheet', 'href' => $url, 'type' => 'text/css' );
/**
* @return string The doctype, opening <html>, and head element.
*/
- public function headElement() {
+ public function headElement( Skin $sk ) {
global $wgDocType, $wgDTD, $wgContLanguageCode, $wgOutputEncoding, $wgMimeType;
global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces;
global $wgUser, $wgContLang, $wgUseTrackbacks, $wgTitle, $wgStyleVersion;
+ $this->addMeta( "http:Content-type", "$wgMimeType; charset={$wgOutputEncoding}" );
+ $this->addStyle( 'common/wikiprintable.css', 'print' );
+ $sk->setupUserCss( $this );
+
+ $ret = '';
+
if( $wgMimeType == 'text/xml' || $wgMimeType == 'application/xhtml+xml' || $wgMimeType == 'application/xml' ) {
- $ret = "<?xml version=\"1.0\" encoding=\"$wgOutputEncoding\" ?>\n";
- } else {
- $ret = '';
+ $ret .= "<?xml version=\"1.0\" encoding=\"$wgOutputEncoding\" ?>\n";
}
$ret .= "<!DOCTYPE html PUBLIC \"$wgDocType\"\n \"$wgDTD\">\n";
$ret .= "xmlns:{$tag}=\"{$ns}\" ";
}
$ret .= "xml:lang=\"$wgContLanguageCode\" lang=\"$wgContLanguageCode\" $rtl>\n";
- $ret .= "<head>\n<title>" . htmlspecialchars( $this->getHTMLTitle() ) . "</title>\n";
- $this->addMeta( "http:Content-type", "$wgMimeType; charset={$wgOutputEncoding}" );
-
- $ret .= $this->getHeadLinks();
- global $wgStylePath;
- if( $this->isPrintable() ) {
- $media = '';
- } else {
- $media = "media='print'";
- }
- $printsheet = htmlspecialchars( "$wgStylePath/common/wikiprintable.css?$wgStyleVersion" );
- $ret .= "<link rel='stylesheet' type='text/css' $media href='$printsheet' />\n";
-
- $sk = $wgUser->getSkin();
- // Load order here is key
- $ret .= $sk->getHeadScripts( $this->mAllowUserJs );
- $ret .= $this->mScripts;
- $ret .= $sk->getSiteStyles();
- foreach( $this->mExtStyles as $tag ) {
- $ret .= Xml::element( 'link', $tag ) . "\n";
+ $ret .= "<head>\n<title>" . htmlspecialchars( $this->getHTMLTitle() ) . "</title>\n\t\t";
+ $ret .= implode( "\t\t", array(
+ $this->getHeadLinks(),
+ $this->buildCssLinks(),
+ $sk->getHeadScripts( $this->mAllowUserJs ),
+ $this->mScripts,
+ $this->getHeadItems(),
+ ));
+ if( $sk->usercss ){
+ $ret .= "<style type='text/css'>{$sk->usercss}</style>";
}
- $ret .= $sk->getUserStyles();
- $ret .= $this->getHeadItems();
if ($wgUseTrackbacks && $this->isArticleRelated())
$ret .= $wgTitle->trackbackRDF();
'href' => $url ) );
}
+ /**
+ * Add a local or specified stylesheet, with the given media options.
+ * Meant primarily for internal use...
+ *
+ * @param $media -- to specify a media type, 'screen', 'printable', 'handheld' or any.
+ * @param $conditional -- for IE conditional comments, specifying an IE version
+ * @param $dir -- set to 'rtl' or 'ltr' for direction-specific sheets
+ */
+ public function addStyle( $style, $media='', $condition='', $dir='' ) {
+ $options = array();
+ if( $media )
+ $options['media'] = $media;
+ if( $condition )
+ $options['condition'] = $condition;
+ if( $dir )
+ $options['dir'] = $dir;
+ $this->styles[$style] = $options;
+ }
+
+ /**
+ * Build a set of <link>s for the stylesheets specified in the $this->styles array.
+ * These will be applied to various media & IE conditionals.
+ */
+ public function buildCssLinks() {
+ $links = array();
+ foreach( $this->styles as $file => $options ) {
+ $link = $this->styleLink( $file, $options );
+ if( $link )
+ $links[] = $link;
+ }
+
+ return implode( "\n\t\t", $links );
+ }
+
+ protected function styleLink( $style, $options ) {
+ global $wgRequest;
+
+ if( isset( $options['dir'] ) ) {
+ global $wgContLang;
+ $siteDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
+ if( $siteDir != $options['dir'] )
+ return '';
+ }
+
+ if( isset( $options['media'] ) ) {
+ $media = $this->transformCssMedia( $options['media'] );
+ if( is_null( $media ) ) {
+ return '';
+ }
+ } else {
+ $media = '';
+ }
+
+ if( substr( $style, 0, 1 ) == '/' ||
+ substr( $style, 0, 5 ) == 'http:' ||
+ substr( $style, 0, 6 ) == 'https:' ) {
+ $url = $style;
+ } else {
+ global $wgStylePath, $wgStyleVersion;
+ $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
+ }
+
+ $attribs = array(
+ 'rel' => 'stylesheet',
+ 'href' => $url,
+ 'type' => 'text/css' );
+ if( $media ) {
+ $attribs['media'] = $media;
+ }
+
+ $link = Xml::element( 'link', $attribs );
+
+ if( isset( $options['condition'] ) ) {
+ $condition = htmlspecialchars( $options['condition'] );
+ $link = "<!--[if $condition]>$link<![endif]-->";
+ }
+ return $link;
+ }
+
+ function transformCssMedia( $media ) {
+ global $wgRequest, $wgHandheldForIPhone;
+
+ // Switch in on-screen display for media testing
+ $switches = array(
+ 'printable' => 'print',
+ 'handheld' => 'handheld',
+ );
+ foreach( $switches as $switch => $targetMedia ) {
+ if( $wgRequest->getBool( $switch ) ) {
+ if( $media == $targetMedia ) {
+ $media = '';
+ } elseif( $media == 'screen' ) {
+ return null;
+ }
+ }
+ }
+
+ // Expand longer media queries as iPhone doesn't grok 'handheld'
+ if( $wgHandheldForIPhone ) {
+ $mediaAliases = array(
+ 'screen' => 'screen and (min-device-width: 481px)',
+ 'handheld' => 'handheld, only screen and (max-device-width: 480px)',
+ );
+
+ if( isset( $mediaAliases[$media] ) ) {
+ $media = $mediaAliases[$media];
+ }
+ }
+
+ return $media;
+ }
+
/**
* Turn off regular page output and return an error reponse
* for when rate limiting has triggered.
global $wgUser, $wgOut, $wgRequest;
if($this->mGen) {
$sk = $wgUser->getSkin();
- $sk->initPage($wgOut);
+ if( !StubObject::isRealObject( $wgOut ) )
+ $wgOut->_unstub( 2 );
+ $sk->initPage( $wgOut );
if($this->mGen == 'css') {
- return $sk->getUserStylesheet();
+ return $sk->generateUserStylesheet();
} else if($this->mGen == 'js') {
- return $sk->getUserJs();
+ return $sk->generateUserJs();
}
} else {
return $this->getArticleText();
return $q;
}
- function initPage( &$out ) {
+ function initPage( OutputPage $out ) {
global $wgFavicon, $wgAppleTouchIcon;
wfProfileIn( __METHOD__ );
$lb->execute();
}
- function addMetadataLinks( &$out ) {
+ function addMetadataLinks( OutputPage $out ) {
global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf;
global $wgRightsPage, $wgRightsUrl;
}
}
- function outputPage( &$out ) {
- global $wgDebugComments;
+ function setMembers(){
+ global $wgTitle, $wgUser;
+ $this->mTitle = $wgTitle;
+ $this->mUser = $wgUser;
+ $this->userpage = $wgUser->getUserPage()->getPrefixedText();
+ $this->usercss = false;
+ }
+ function outputPage( OutputPage $out ) {
+ global $wgDebugComments;
wfProfileIn( __METHOD__ );
+
+ $this->setMembers();
$this->initPage( $out );
// See self::afterContentHook() for documentation
$afterContent = $this->afterContentHook();
- $out->out( $out->headElement() );
+ $out->out( $out->headElement( $this ) );
$out->out( "\n<body" );
$ops = $this->getBodyOptions();
'wgScriptPath' => $wgScriptPath,
'wgScript' => $wgScript,
'wgVariantArticlePath' => $wgVariantArticlePath,
- 'wgActionPaths' => $wgActionPaths,
+ 'wgActionPaths' => (object)$wgActionPaths,
'wgServer' => $wgServer,
'wgCanonicalNamespace' => $nsname,
'wgCanonicalSpecialPageName' => SpecialPage::resolveAlias( $wgTitle->getDBkey() ),
function getHeadScripts( $allowUserJs ) {
global $wgStylePath, $wgUser, $wgJsMimeType, $wgStyleVersion;
- $r = self::makeGlobalVariablesScript( array( 'skinname' => $this->getSkinName() ) );
+ $vars = self::makeGlobalVariablesScript( array( 'skinname' => $this->getSkinName() ) );
- $r .= "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/wikibits.js?$wgStyleVersion\"></script>\n";
+ $r = array( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/wikibits.js?$wgStyleVersion\"></script>" );
global $wgUseSiteJs;
if ($wgUseSiteJs) {
$jsCache = $wgUser->isLoggedIn() ? '&smaxage=0' : '';
- $r .= "<script type=\"$wgJsMimeType\" src=\"".
+ $r[] = "<script type=\"$wgJsMimeType\" src=\"".
htmlspecialchars(self::makeUrl('-',
"action=raw$jsCache&gen=js&useskin=" .
urlencode( $this->getSkinName() ) ) ) .
- "\"><!-- site js --></script>\n";
+ "\"><!-- site js --></script>";
}
if( $allowUserJs && $wgUser->isLoggedIn() ) {
$userpage = $wgUser->getUserPage();
$userjs = htmlspecialchars( self::makeUrl(
$userpage->getPrefixedText().'/'.$this->getSkinName().'.js',
'action=raw&ctype='.$wgJsMimeType));
- $r .= '<script type="'.$wgJsMimeType.'" src="'.$userjs."\"></script>\n";
+ $r[] = '<script type="'.$wgJsMimeType.'" src="'.$userjs."\"></script>";
}
- return $r;
+ return $vars . "\t\t" . implode ( "\n\t\t", $r );
}
/**
}
/**
- * Get the site-specific stylesheet, SkinTemplate loads via RawPage.php (settings are cached that way)
- */
- function getSiteStylesheet() {
- global $wgStylePath, $wgContLang, $wgStyleVersion;
- $sheet = $this->getStylesheet();
- $s = "@import \"$wgStylePath/common/shared.css?$wgStyleVersion\";\n";
- $s .= "@import \"$wgStylePath/common/oldshared.css?$wgStyleVersion\";\n";
- $s .= "@import \"$wgStylePath/$sheet?$wgStyleVersion\";\n";
- if( $wgContLang->isRTL() )
- $s .= "@import \"$wgStylePath/common/common_rtl.css?$wgStyleVersion\";\n";
- return "$s\n";
- }
-
- /**
- * Get the user-specific stylesheet, SkinTemplate loads via RawPage.php (settings are cached that way)
- */
- function getUserStylesheet() {
- global $wgContLang, $wgSquidMaxage, $wgStyleVersion;
- $query = "usemsgcache=yes&action=raw&ctype=text/css&smaxage=$wgSquidMaxage";
- $s = '@import "' . self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI ) . "\";\n";
- $s .= '@import "' . self::makeNSUrl( ucfirst( $this->getSkinName() . '.css' ), $query, NS_MEDIAWIKI ) . "\";\n";
- $s .= $this->doGetUserStyles();
- return "$s\n";
- }
-
- /**
- * This returns MediaWiki:Common.js, and derived classes may add other JS.
- * Despite its name, it does *not* return any custom user JS from user
- * subpages. The returned script is sitewide and publicly cacheable and
- * therefore must not include anything that varies according to user,
- * interface language, etc. (although it may vary by skin). See
- * makeGlobalVariablesScript for things that can vary per page view and are
- * not cacheable.
+ * generated JavaScript action=raw&gen=js
+ * This returns MediaWiki:Common.js and MediaWiki:[Skinname].js concate-
+ * nated together. For some bizarre reason, it does *not* return any
+ * custom user JS from subpages. Huh?
+ *
+ * There's absolutely no reason to have separate Monobook/Common JSes.
+ * Any JS that cares can just check the skin variable generated at the
+ * top. For now Monobook.js will be maintained, but it should be consi-
+ * dered deprecated.
*
- * @return string Raw JavaScript to be returned
+ * @return string
*/
- public function getUserJs() {
+ public function generateUserJs() {
+ global $wgStylePath;
+
wfProfileIn( __METHOD__ );
- global $wgStylePath;
$s = "/* generated javascript */\n";
$s .= "var skin = '" . Xml::escapeJsString( $this->getSkinName() ) . "';\n";
$s .= "var stylepath = '" . Xml::escapeJsString( $wgStylePath ) . "';";
if ( !wfEmptyMsg ( 'common.js', $commonJs ) ) {
$s .= $commonJs;
}
+
+ $s .= "\n\n/* MediaWiki:".ucfirst( $this->getSkinName() ).".js */\n";
+ // avoid inclusion of non defined user JavaScript (with custom skins only)
+ // by checking for default message content
+ $msgKey = ucfirst( $this->getSkinName() ).'.js';
+ $userJS = wfMsgForContent($msgKey);
+ if ( !wfEmptyMsg( $msgKey, $userJS ) ) {
+ $s .= $userJS;
+ }
+
wfProfileOut( __METHOD__ );
return $s;
}
/**
- * Return html code that include site stylesheets
+ * generate user stylesheet for action=raw&gen=css
*/
- function getSiteStyles() {
- $s = "<style type='text/css'>\n";
- $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
- $s .= $this->getSiteStylesheet();
- $s .= "/*]]>*/ /* */\n";
- $s .= "</style>\n";
+ public function generateUserStylesheet() {
+ wfProfileIn( __METHOD__ );
+ $s = "/* generated user stylesheet */\n" .
+ $this->reallyGenerateUserStylesheet();
+ wfProfileOut( __METHOD__ );
return $s;
}
/**
- * Return html code that include User stylesheets
+ * Split for easier subclassing in SkinSimple, SkinStandard and SkinCologneBlue
*/
- function getUserStyles() {
- $s = "<style type='text/css'>\n";
- $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
- $s .= $this->getUserStylesheet();
- $s .= "/*]]>*/ /* */\n";
- $s .= "</style>\n";
- return $s;
- }
-
- /**
- * Some styles that are set by user through the user settings interface.
- */
- function doGetUserStyles() {
- global $wgUser, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
-
- $s = '';
-
- if( $wgAllowUserCss && $wgUser->isLoggedIn() ) { # logged in
- if($wgTitle->isCssSubpage() && $this->userCanPreview( $wgRequest->getText( 'action' ) ) ) {
- $s .= $wgRequest->getText('wpTextbox1');
- } else {
- $userpage = $wgUser->getUserPage();
- $s.= '@import "'.self::makeUrl(
- $userpage->getPrefixedText().'/'.$this->getSkinName().'.css',
- 'action=raw&ctype=text/css').'";'."\n";
- }
- }
-
- return $s . $this->reallyDoGetUserStyles();
- }
-
- function reallyDoGetUserStyles() {
+ protected function reallyGenerateUserStylesheet(){
global $wgUser;
$s = '';
if (($undopt = $wgUser->getOption("underline")) < 2) {
return $s;
}
+ /**
+ * @private
+ */
+ function setupUserCss( OutputPage $out ) {
+ global $wgRequest, $wgContLang, $wgUser;
+ global $wgAllowUserCss, $wgUseSiteCss, $wgSquidMaxage, $wgStylePath;
+
+ wfProfileIn( __METHOD__ );
+
+ $this->setupSkinUserCss( $out );
+
+ $siteargs = array(
+ 'action' => 'raw',
+ 'maxage' => $wgSquidMaxage,
+ );
+ if( $wgUser->isLoggedIn() ) {
+ // Ensure that logged-in users' generated CSS isn't clobbered
+ // by anons' publicly cacheable generated CSS.
+ $siteargs['smaxage'] = '0';
+ $siteargs['ts'] = $wgUser->mTouched;
+ }
+
+ // Add any extension CSS
+ foreach( $out->getExtStyle() as $tag ) {
+ $out->addStyle( $tag['href'] );
+ }
+
+ // If we use the site's dynamic CSS, throw that in, too
+ // Per-site custom styles
+ if( $wgUseSiteCss ) {
+ $query = wfArrayToCGI( array(
+ 'usemsgcache' => 'yes',
+ 'ctype' => 'text/css',
+ 'smaxage' => $wgSquidMaxage
+ ) + $siteargs );
+ # Site settings must override extension css! (bug 15025)
+ $out->addStyle( self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI) );
+ $out->addStyle( self::makeNSUrl( $this->getSkinName() . '.css', $query, NS_MEDIAWIKI ) );
+ }
+
+ // Per-user styles based on preferences
+ $siteargs['gen'] = 'css';
+ if( ( $us = $wgRequest->getVal( 'useskin', '' ) ) !== '' ) {
+ $siteargs['useskin'] = $us;
+ }
+ $out->addStyle( self::makeUrl( '-', wfArrayToCGI( $siteargs ) ) );
+
+ // Per-user custom style pages
+ if( $wgAllowUserCss && $wgUser->isLoggedIn() ) {
+ $action = $wgRequest->getVal('action');
+ # If we're previewing the CSS page, use it
+ if( $this->mTitle->isCssSubpage() && $this->userCanPreview( $action ) ) {
+ $previewCss = $wgRequest->getText('wpTextbox1');
+ // @FIXME: properly escape the cdata!
+ $this->usercss = "/*<![CDATA[*/\n" . $previewCss . "/*]]>*/";
+ } else {
+ $out->addStyle( self::makeUrl($this->userpage .'/'.$this->getSkinName() .'.css',
+ 'action=raw&ctype=text/css') );
+ }
+ }
+
+ wfProfileOut( __METHOD__ );
+ }
+
+ /**
+ * Add skin specific stylesheets
+ * @param $out OutputPage
+ */
+ function setupSkinUserCss( OutputPage $out ) {
+ $out->addStyle( 'common/shared.css' );
+ $out->addStyle( 'common/oldshared.css' );
+ $out->addStyle( $this->getStylesheet() );
+ $out->addStyle( 'common/common_rtl.css', '', '', 'rtl' );
+ }
+
function getBodyOptions() {
global $wgUser, $wgTitle, $wgOut, $wgRequest, $wgContLang;
$s .= "\n<div id='content'>\n<div id='topbar'>\n" .
"<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
- $shove = ($qb != 0);
- $left = ($qb == 1 || $qb == 3);
- if($wgContLang->isRTL()) $left = !$left;
+ $shove = ( $qb != 0 );
+ $left = ( $qb == 1 || $qb == 3 );
+ if( $wgContLang->isRTL() ) $left = !$left;
- if ( !$shove ) {
+ if( !$shove ) {
$s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
$this->logoText() . '</td>';
} elseif( $left ) {
# optional 'dmoz-like' category browser. Will be shown under the list
# of categories an article belong to
- if($wgUseCategoryBrowser) {
+ if( $wgUseCategoryBrowser ){
$s .= '<br /><hr />';
# get a big array of the parents tree
* @param &skin Object: skin passed by reference
* @return String separated by >, terminate with "\n"
*/
- function drawCategoryBrowser($tree, &$skin) {
+ function drawCategoryBrowser( $tree, &$skin ){
$return = '';
foreach ($tree as $element => $parent) {
if (empty($parent)) {
*
* Returns an empty string by default, if not changed by any hook function.
*/
- protected function afterContentHook () {
+ protected function afterContentHook() {
$data = "";
- if (wfRunHooks ('SkinAfterContent', array (&$data))) {
+ if( wfRunHooks( 'SkinAfterContent', array( &$data ) ) ){
// adding just some spaces shouldn't toggle the output
// of the whole <div/>, so we use trim() here
- if (trim ($data) != "") {
+ if( trim( $data ) != '' ){
// Doing this here instead of in the skins to
// ensure that the div has the same ID in all
// skins
"</div>\n";
}
} else {
- wfDebug ('Hook SkinAfterContent changed output processing.');
+ wfDebug( "Hook SkinAfterContent changed output processing.\n" );
}
return $data;
}
/**
- * This gets called shortly before the \</body\> tag.
- * @return String HTML to be put before \</body\>
+ * This gets called shortly before the </body> tag.
+ * @return String HTML to be put before </body>
*/
function afterContent() {
$printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
}
/**
- * This gets called shortly before the \</body\> tag.
- * @return String HTML-wrapped JS code to be put before \</body\>
+ * This gets called shortly before the </body> tag.
+ * @return String HTML-wrapped JS code to be put before </body>
*/
function bottomScripts() {
global $wgJsMimeType;
}
/** overloaded by derived classes */
- function doAfterContent() { }
+ function doAfterContent() { return "</div></div>"; }
function pageTitleLinks() {
global $wgOut, $wgTitle, $wgUser, $wgRequest;
*/
var $template;
- /**
- * An array of stylesheet filenames (relative from skins path), with options
- * for CSS media, IE conditions, and RTL/LTR direction.
- * For internal use; add settings in the skin via $this->addStyle()
- */
- var $styles = array();
-
/**#@-*/
/**
* Child classes should override this to set the name,
* style subdirectory, and template filler callback.
*
- * @param OutputPage $out
+ * @param $out OutputPage
*/
- function initPage( &$out ) {
+ function initPage( OutputPage $out ) {
parent::initPage( $out );
$this->skinname = 'monobook';
$this->stylename = 'monobook';
$this->template = 'QuickTemplate';
+ }
- $this->addStyle( 'common/shared.css', 'screen' );
- $this->addStyle( 'common/commonPrint.css', 'print' );
+ /**
+ * Add specific styles for this skin
+ *
+ * @param $out OutputPage
+ */
+ function setupSkinUserCss( OutputPage $out ){
+ $out->addStyle( 'common/shared.css', 'screen' );
+ $out->addStyle( 'common/commonPrint.css', 'print' );
}
/**
* and eventually it spits out some HTML. Should have interface
* roughly equivalent to PHPTAL 0.7.
*
- * @param string $callback (or file)
- * @param string $repository subdirectory where we keep template files
- * @param string $cache_dir
+ * @param $callback string (or file)
+ * @param $repository string: subdirectory where we keep template files
+ * @param $cache_dir string
* @return object
* @private
*/
/**
* initialize various variables and generate the template
*
- * @param OutputPage $out
- * @public
+ * @param $out OutputPage
*/
- function outputPage( &$out ) {
- global $wgTitle, $wgArticle, $wgUser, $wgLang, $wgContLang, $wgOut;
+ function outputPage( OutputPage $out ) {
+ global $wgTitle, $wgArticle, $wgUser, $wgLang, $wgContLang;
global $wgScript, $wgStylePath, $wgContLanguageCode;
global $wgMimeType, $wgJsMimeType, $wgOutputEncoding, $wgRequest;
global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces;
wfProfileIn( __METHOD__."-init" );
$this->initPage( $out );
- $this->mTitle =& $wgTitle;
- $this->mUser =& $wgUser;
-
+ $this->setMembers();
$tpl = $this->setupTemplate( $this->template, 'skins' );
#if ( $wgUseDatabaseMessages ) { // uncomment this to fall back to GetText
$this->iscontent = ($this->mTitle->getNamespace() != NS_SPECIAL );
$this->iseditable = ($this->iscontent and !($action == 'edit' or $action == 'submit'));
$this->username = $wgUser->getName();
- $userPage = $wgUser->getUserPage();
- $this->userpage = $userPage->getPrefixedText();
if ( $wgUser->isLoggedIn() || $this->showIPinHeader() ) {
$this->userpageUrlDetails = self::makeUrlDetails( $this->userpage );
$this->userpageUrlDetails = self::makeKnownUrlDetails( $this->userpage );
}
- $this->usercss = $this->userjs = $this->userjsprev = false;
- $this->setupUserCss( $out->getExtStyle() );
+ $this->userjs = $this->userjsprev = false;
+ $this->setupUserCss( $out );
$this->setupUserJs( $out->isUserJsAllowed() );
$this->titletxt = $this->mTitle->getPrefixedText();
wfProfileOut( __METHOD__."-stuff" );
wfProfileIn( __METHOD__."-stuff2" );
- $tpl->set( 'title', $wgOut->getPageTitle() );
- $tpl->set( 'pagetitle', $wgOut->getHTMLTitle() );
- $tpl->set( 'displaytitle', $wgOut->mPageLinkTitle );
+ $tpl->set( 'title', $out->getPageTitle() );
+ $tpl->set( 'pagetitle', $out->getHTMLTitle() );
+ $tpl->set( 'displaytitle', $out->mPageLinkTitle );
$tpl->set( 'pageclass', $this->getPageClasses( $this->mTitle ) );
$tpl->set( 'skinnameclass', ( "skin-" . Sanitizer::escapeClass( $this->getSkinName ( ) ) ) );
$tpl->set( 'articleid', $this->mTitle->getArticleId() );
$tpl->set( 'currevisionid', isset( $wgArticle ) ? $wgArticle->getLatest() : 0 );
- $tpl->set( 'isarticle', $wgOut->isArticle() );
+ $tpl->set( 'isarticle', $out->isArticle() );
$tpl->setRef( "thispage", $this->thispage );
$subpagestr = $this->subPageSubtitle();
);
$tpl->set( 'catlinks', $this->getCategories());
- if( $wgOut->isSyndicated() ) {
+ if( $out->isSyndicated() ) {
$feeds = array();
- foreach( $wgOut->getSyndicationLinks() as $format => $link ) {
+ foreach( $out->getSyndicationLinks() as $format => $link ) {
$feeds[$format] = array(
'text' => wfMsg( "feed-$format" ),
'href' => $link );
$tpl->setRef( 'jsmimetype', $wgJsMimeType );
$tpl->setRef( 'charset', $wgOutputEncoding );
$tpl->set( 'headlinks', $out->getHeadLinks() );
- $tpl->set('headscripts', $out->getScript() );
+ $tpl->set( 'headscripts', $out->getScript() );
+ $tpl->set( 'csslinks', $out->buildCssLinks() );
$tpl->setRef( 'wgScript', $wgScript );
$tpl->setRef( 'skinname', $this->skinname );
$tpl->set( 'skinclass', get_class( $this ) );
$tpl->setRef( 'stylename', $this->stylename );
$tpl->set( 'printable', $wgRequest->getBool( 'printable' ) );
$tpl->set( 'handheld', $wgRequest->getBool( 'handheld' ) );
- $tpl->set( 'csslinks', $this->buildCssLinks() );
$tpl->setRef( 'loggedin', $this->loggedin );
$tpl->set('notspecialpage', $this->mTitle->getNamespace() != NS_SPECIAL);
/* XXX currently unused, might get useful later
)
);
# Disable Cache
- $wgOut->setSquidMaxage(0);
+ $out->setSquidMaxage(0);
}
} else if (count($newtalks)) {
$sep = str_replace("_", " ", wfMsgHtml("newtalkseperator"));
}
$parts = implode($sep, $msgs);
$ntl = wfMsgHtml('youhavenewmessagesmulti', $parts);
- $wgOut->setSquidMaxage(0);
+ $out->setSquidMaxage(0);
} else {
$ntl = '';
}
$tpl->setRef( 'newtalk', $ntl );
$tpl->setRef( 'skin', $this );
$tpl->set( 'logo', $this->logoText() );
- if ( $wgOut->isArticle() and (!isset( $oldid ) or isset( $diff )) and
+ if ( $out->isArticle() and (!isset( $oldid ) or isset( $diff )) and
$wgArticle and 0 != $wgArticle->getID() )
{
if ( !$wgDisableCounters ) {
$language_urls = array();
if ( !$wgHideInterlanguageLinks ) {
- foreach( $wgOut->getLanguageLinks() as $l ) {
+ foreach( $out->getLanguageLinks() as $l ) {
$tmp = explode( ':', $l, 2 );
$class = 'interwiki-' . $tmp[0];
unset($tmp);
* @return array
* @private
*/
- function buildContentActionUrls () {
+ function buildContentActionUrls() {
global $wgContLang, $wgLang, $wgOut;
wfProfileIn( __METHOD__ );
* @return array
* @private
*/
- function buildNavUrls () {
+ function buildNavUrls() {
global $wgUseTrackbacks, $wgTitle, $wgUser, $wgRequest;
global $wgEnableUploads, $wgUploadNavigationUrl;
* @return string
* @private
*/
- function getNameSpaceKey () {
+ function getNameSpaceKey() {
return $this->mTitle->getNamespaceKey();
}
- /**
- * @private
- */
- function setupUserCss( $extCSS = array() ) {
- global $wgRequest, $wgAllowUserCss, $wgUseSiteCss, $wgContLang, $wgSquidMaxage, $wgStylePath, $wgUser;
-
- wfProfileIn( __METHOD__ );
-
- $siteargs = array(
- 'action' => 'raw',
- 'maxage' => $wgSquidMaxage,
- );
- if( $this->loggedin ) {
- // Ensure that logged-in users' generated CSS isn't clobbered
- // by anons' publicly cacheable generated CSS.
- $siteargs['smaxage'] = '0';
- $siteargs['ts'] = $wgUser->mTouched;
- }
-
- // Add any extension CSS
- foreach( $extCSS as $tag ) {
- $this->addStyle( $tag['href'] );
- }
-
- // If we use the site's dynamic CSS, throw that in, too
- // Per-site custom styles
- if ( $wgUseSiteCss ) {
- $query = wfArrayToCGI( array(
- 'usemsgcache' => 'yes',
- 'ctype' => 'text/css',
- 'smaxage' => $wgSquidMaxage
- ) + $siteargs );
- $this->addStyle( self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI ) );
- $this->addStyle( self::makeNSUrl( ucfirst( $this->skinname ) . '.css', $query, NS_MEDIAWIKI ),
- 'screen' );
- }
-
- // Per-user styles based on preferences
- $siteargs['gen'] = 'css';
- if( ( $us = $wgRequest->getVal( 'useskin', '' ) ) !== '' )
- $siteargs['useskin'] = $us;
- $this->addStyle( self::makeUrl( '-', wfArrayToCGI( $siteargs ) ), 'screen' );
-
- // Per-user custom style pages
- if ( $wgAllowUserCss && $this->loggedin ) {
- $action = $wgRequest->getVal('action');
-
- # if we're previewing the CSS page, use it
- if( $this->mTitle->isCssSubpage() && $this->userCanPreview( $action ) ) {
- $previewCss = $wgRequest->getText('wpTextbox1');
-
- /// @fixme properly escape the cdata!
- $this->usercss = "/*<![CDATA[*/\n" .
- $previewCss .
- "/*]]>*/";
- } else {
- $this->addStyle( self::makeUrl($this->userpage . '/'.$this->skinname.'.css',
- 'action=raw&ctype=text/css'), 'screen' );
- }
- }
-
- wfProfileOut( __METHOD__ );
- }
-
/**
* @private
*/
wfProfileIn( __METHOD__ );
$out = false;
wfRunHooks( 'SkinTemplateSetupPageCss', array( &$out ) );
-
wfProfileOut( __METHOD__ );
return $out;
}
-
- /**
- * returns css with user-specific options
- */
- public function getUserStylesheet() {
- wfProfileIn( __METHOD__ );
-
- $s = "/* generated user stylesheet */\n";
- $s .= $this->reallyDoGetUserStyles();
- wfProfileOut( __METHOD__ );
- return $s;
- }
-
- /**
- * This returns MediaWiki:Common.js and MediaWiki:[Skinname].js concate-
- * nated together. For some bizarre reason, it does *not* return any
- * custom user JS from subpages. Huh?
- *
- * There's absolutely no reason to have separate Monobook/Common JSes.
- * Any JS that cares can just check the skin variable generated at the
- * top. For now Monobook.js will be maintained, but it should be consi-
- * dered deprecated.
- *
- * @return string
- */
- public function getUserJs() {
- wfProfileIn( __METHOD__ );
-
- $s = parent::getUserJs();
- $s .= "\n\n/* MediaWiki:".ucfirst($this->skinname).".js */\n";
-
- // avoid inclusion of non defined user JavaScript (with custom skins only)
- // by checking for default message content
- $msgKey = ucfirst($this->skinname).'.js';
- $userJS = wfMsgForContent($msgKey);
- if ( !wfEmptyMsg( $msgKey, $userJS ) ) {
- $s .= $userJS;
- }
-
- wfProfileOut( __METHOD__ );
- return $s;
- }
-
- /**
- * Add a local or specified stylesheet, with the given media options.
- * Meant primarily for internal use...
- *
- * @param $media -- to specify a media type, 'screen', 'printable', 'handheld' or any.
- * @param $conditional -- for IE conditional comments, specifying an IE version
- * @param $dir -- set to 'rtl' or 'ltr' for direction-specific sheets
- */
- public function addStyle( $style, $media='', $condition='', $dir='' ) {
- $options = array();
- if( $media )
- $options['media'] = $media;
- if( $condition )
- $options['condition'] = $condition;
- if( $dir )
- $options['dir'] = $dir;
- $this->styles[$style] = $options;
- }
-
- /**
- * Build a set of <link>s for the stylesheets specified in the $this->styles array.
- * These will be applied to various media & IE conditionals.
- */
- protected function buildCssLinks() {
- $links = array();
- foreach( $this->styles as $file => $options ) {
- $link = $this->styleLink( $file, $options );
- if( $link )
- $links[] = $link;
- }
-
- return implode( "\n\t\t", $links );
- }
-
- protected function styleLink( $style, $options ) {
- global $wgRequest;
-
- if( isset( $options['dir'] ) ) {
- global $wgContLang;
- $siteDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
- if( $siteDir != $options['dir'] )
- return '';
- }
-
- if( isset( $options['media'] ) ) {
- $media = $this->transformCssMedia( $options['media'] );
- if( is_null( $media ) ) {
- return '';
- }
- } else {
- $media = '';
- }
-
- if( substr( $style, 0, 1 ) == '/' ||
- substr( $style, 0, 5 ) == 'http:' ||
- substr( $style, 0, 6 ) == 'https:' ) {
- $url = $style;
- } else {
- global $wgStylePath, $wgStyleVersion;
- $url = $wgStylePath . '/' . $style . '?' . $wgStyleVersion;
- }
-
- $attribs = array(
- 'rel' => 'stylesheet',
- 'href' => $url,
- 'type' => 'text/css' );
- if( $media ) {
- $attribs['media'] = $media;
- }
-
- $link = Xml::element( 'link', $attribs );
-
- if( isset( $options['condition'] ) ) {
- $condition = htmlspecialchars( $options['condition'] );
- $link = "<!--[if $condition]>$link<![endif]-->";
- }
- return $link;
- }
-
- function transformCssMedia( $media ) {
- global $wgRequest, $wgHandheldForIPhone;
-
- // Switch in on-screen display for media testing
- $switches = array(
- 'printable' => 'print',
- 'handheld' => 'handheld',
- );
- foreach( $switches as $switch => $targetMedia ) {
- if( $wgRequest->getBool( $switch ) ) {
- if( $media == $targetMedia ) {
- $media = '';
- } elseif( $media == 'screen' ) {
- return null;
- }
- }
- }
-
- // Expand longer media queries as iPhone doesn't grok 'handheld'
- if( $wgHandheldForIPhone ) {
- $mediaAliases = array(
- 'screen' => 'screen and (min-device-width: 481px)',
- 'handheld' => 'handheld, only screen and (max-device-width: 480px)',
- );
-
- if( isset( $mediaAliases[$media] ) ) {
- $media = $mediaAliases[$media];
- }
- }
-
- return $media;
- }
-
}
/**
* @ingroup Skins
*/
class SkinChick extends SkinTemplate {
- function initPage( &$out ) {
+ function initPage( OutputPage $out ) {
SkinTemplate::initPage( $out );
$this->skinname = 'chick';
$this->stylename = 'chick';
$this->template = 'MonoBookTemplate';
+ }
+ function setupSkinUserCss( OutputPage $out ){
+ parent::setupSkinUserCss( $out );
// Append to the default screen common & print styles...
- $this->addStyle( 'chick/main.css', 'screen,handheld' );
- $this->addStyle( 'chick/IE50Fixes.css', 'screen,handheld', 'lt IE 5.5000' );
- $this->addStyle( 'chick/IE55Fixes.css', 'screen,handheld', 'IE 5.5000' );
- $this->addStyle( 'chick/IE60Fixes.css', 'screen,handheld', 'IE 6' );
+ $out->addStyle( 'chick/main.css', 'screen,handheld' );
+ $out->addStyle( 'chick/IE50Fixes.css', 'screen,handheld', 'lt IE 5.5000' );
+ $out->addStyle( 'chick/IE55Fixes.css', 'screen,handheld', 'IE 5.5000' );
+ $out->addStyle( 'chick/IE60Fixes.css', 'screen,handheld', 'IE 6' );
}
}
return $s;
}
- function doGetUserStyles() {
- global $wgOut;
- $s = parent::doGetUserStyles();
+ function reallyGenerateUserStylesheet() {
+ $s = parent::reallyGenerateUserStylesheet();
$qb = $this->qbSetting();
if ( 2 == $qb ) { # Right
return "<div class='mw_poweredby'>Powered by MediaWiki $wgVersion</div>";
}
- function initPage( &$out ) {
- Skin::initPage( $out );
+ function initPage( OutputPage $out ) {
+ parent::initPage( $out );
$this->skinname = 'modern';
$this->stylename = 'modern';
$this->template = 'ModernTemplate';
-
- $this->addStyle( 'common/shared.css', 'screen' );
- $this->addStyle( 'modern/main.css', 'screen' );
- $this->addStyle( 'modern/print.css', 'print' );
+ }
+
+ function setupSkinUserCss( OutputPage $out ){
+ // Do not call parent::setupSkinUserCss(), we have our own print style
+ $out->addStyle( 'common/shared.css', 'screen' );
+ $out->addStyle( 'modern/main.css', 'screen' );
+ $out->addStyle( 'modern/print.css', 'print' );
}
}
*/
class SkinMonoBook extends SkinTemplate {
/** Using monobook. */
- function initPage( &$out ) {
- global $wgHandheldStyle;
-
- SkinTemplate::initPage( $out );
+ function initPage( OutputPage $out ) {
+ parent::initPage( $out );
$this->skinname = 'monobook';
$this->stylename = 'monobook';
$this->template = 'MonoBookTemplate';
+ }
+
+ function setupSkinUserCss( OutputPage $out ) {
+ global $wgHandheldStyle;
+
+ parent::setupSkinUserCss( $out );
+
// Append to the default screen common & print styles...
- $this->addStyle( 'monobook/main.css', 'screen' );
+ $out->addStyle( 'monobook/main.css', 'screen' );
if( $wgHandheldStyle ) {
// Currently in testing... try 'chick/main.css'
- $this->addStyle( $wgHandheldStyle, 'handheld' );
+ $out->addStyle( $wgHandheldStyle, 'handheld' );
}
- $this->addStyle( 'monobook/IE50Fixes.css', 'screen', 'lt IE 5.5000' );
- $this->addStyle( 'monobook/IE55Fixes.css', 'screen', 'IE 5.5000' );
- $this->addStyle( 'monobook/IE60Fixes.css', 'screen', 'IE 6' );
- $this->addStyle( 'monobook/IE70Fixes.css', 'screen', 'IE 7' );
+ $out->addStyle( 'monobook/IE50Fixes.css', 'screen', 'lt IE 5.5000' );
+ $out->addStyle( 'monobook/IE55Fixes.css', 'screen', 'IE 5.5000' );
+ $out->addStyle( 'monobook/IE60Fixes.css', 'screen', 'IE 6' );
+ $out->addStyle( 'monobook/IE70Fixes.css', 'screen', 'IE 7' );
- $this->addStyle( 'monobook/rtl.css', 'screen', '', 'rtl' );
+ $out->addStyle( 'monobook/rtl.css', 'screen', '', 'rtl' );
}
}
if( !defined( 'MEDIAWIKI' ) )
die( -1 );
-/** */
-require_once( dirname(__FILE__) . '/MonoBook.php' );
-
/**
* @todo document
* @ingroup Skins
*/
class SkinMySkin extends SkinTemplate {
- function initPage( &$out ) {
- SkinTemplate::initPage( $out );
+ function initPage( OutputPage $out ) {
+ parent::initPage( $out );
$this->skinname = 'myskin';
$this->stylename = 'myskin';
$this->template = 'MonoBookTemplate';
}
}
-
-
* @ingroup Skins
*/
class SkinSimple extends SkinTemplate {
- function initPage( &$out ) {
+ function initPage( OutputPage $out ) {
SkinTemplate::initPage( $out );
$this->skinname = 'simple';
$this->stylename = 'simple';
$this->template = 'MonoBookTemplate';
- $this->addStyle( 'simple/main.css', 'screen' );
- $this->addStyle( 'simple/rtl.css', '', '', 'rtl' );
+ }
+
+ function setupSkinUserCss( OutputPage $out ){
+ $out->addStyle( 'simple/main.css', 'screen' );
+ $out->addStyle( 'simple/rtl.css', '', '', 'rtl' );
}
- function reallyDoGetUserStyles() {
+ function reallyGenerateUserStylesheet() {
global $wgUser;
$s = '';
if (($undopt = $wgUser->getOption("underline")) != 2) {
/**
*
*/
- function getUserStyles() {
- global $wgStylePath, $wgStyleVersion;
- $s = '';
+ function setupSkinUserCss( OutputPage $out ){
if ( 3 == $this->qbSetting() ) { # Floating left
- $s .= "<style type='text/css'>\n" .
- "@import '{$wgStylePath}/common/quickbar.css?$wgStyleVersion';\n</style>\n";
+ $out->addStyle( 'common/quickbar.css' );
} else if ( 4 == $this->qbSetting() ) { # Floating right
- $s .= "<style type='text/css'>\n" .
- "@import '{$wgStylePath}/common/quickbar-right.css?$wgStyleVersion';\n</style>\n";
+ $out->addStyle( 'common/quickbar-right.css' );
}
- $s .= parent::getUserStyles();
- return $s;
+ parent::setupSkinUserCss( $out );
}
/**
*
*/
- function doGetUserStyles() {
- global $wgStylePath;
-
- $s = parent::doGetUserStyles();
+ function reallyGenerateUserStylesheet() {
+ $s = parent::reallyGenerateUserStylesheet();
$qb = $this->qbSetting();
if ( 2 == $qb ) { # Right
$id=User::idFromName($wgTitle->getText());
$ip=User::isIP($wgTitle->getText());
- if($id||$ip) {
+ if( $id || $ip ){
$s .= $sep . $this->userContribsLink();
}
if( $this->showEmailUser( $id ) ) {
}
-
-