From a99f9ec28b9aa9df98740cb9da37850011834663 Mon Sep 17 00:00:00 2001 From: Trevor Parscal Date: Sat, 11 Sep 2010 03:26:15 +0000 Subject: [PATCH] Major refactoring of site and user CSS, creating ResourceLoaderUserModule and ResourceLoaderUserPreferenceModule. Also moved as much of the global variables being generated in Skin::makeGlobalVaiablesScript into the ResourceLoaderStartupModule - which will make configuration changes effective site-wide in 5 minutes instead of whenever all pages are purged from cache - what remains embedded in the HTML is article and user specific - two things we don't know by the time we request the startup module. Also, fixed issue where debug=false was being interpreted to be equivilant to debug=true. Finally, finished integrating the introduction of $wgLoadScript, thus fixing overlooked issues in r72763. --- includes/OutputPage.php | 30 ++- includes/ResourceLoaderContext.php | 17 +- includes/ResourceLoaderModule.php | 285 +++++++++++++++++++++-------- includes/Skin.php | 235 ++++-------------------- load.php | 2 +- resources/Resources.php | 3 + resources/mediawiki/mediawiki.js | 2 +- 7 files changed, 279 insertions(+), 295 deletions(-) diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 93f245fb4b..c22882bf9b 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -2283,19 +2283,33 @@ class OutputPage { static function makeResourceLoaderLink( $skin, $modules, $only ) { global $wgUser, $wgLang, $wgRequest, $wgLoadScript; // TODO: Should this be a static function of ResourceLoader instead? + // TODO: Divide off modules starting with "user", and add the user parameter to them $query = array( - 'modules' => implode( '|', array_unique( (array) $modules ) ), 'lang' => $wgLang->getCode(), 'debug' => $wgRequest->getBool( 'debug' ) && $wgRequest->getVal( 'debug' ) !== 'false', 'skin' => $wgUser->getSkin()->getSkinName(), 'only' => $only, ); - // Automatically select style/script elements - if ( $only === 'styles' ) { - return Html::linkedStyle( wfAppendQuery( $wgLoadScript, $query ) ); - } else { - return Html::linkedScript( wfAppendQuery( $wgLoadScript, $query ) ); + $moduleGroups = array( null => array(), 'user' => array() ); + foreach ( (array) $modules as $module ) { + $moduleGroups[strpos( $module, 'user' ) === 0 ? 'user' : null][] = $module; + } + $links = ''; + foreach ( $moduleGroups as $group => $modules ) { + if ( count( $modules ) ) { + $query['modules'] = implode( '|', array_unique( (array) $modules ) ); + if ( $group === 'user' ) { + $query['user'] = $wgUser->getName(); + } + // Automatically select style/script elements + if ( $only === 'styles' ) { + $links .= Html::linkedStyle( wfAppendQuery( $wgLoadScript, $query ) ); + } else { + $links .= Html::linkedScript( wfAppendQuery( $wgLoadScript, $query ) ); + } + } } + return $links; } /** @@ -2313,8 +2327,8 @@ class OutputPage { // Statup - this will immediately load jquery and mediawiki modules $scripts = self::makeResourceLoaderLink( $sk, 'startup', 'scripts' ); - // Configuration -- this could be merged together with the load and go, but makeGlobalVariablesScript returns a - // whole script tag -- grumble grumble + // Configuration -- This could be merged together with the load and go, but makeGlobalVariablesScript returns a + // whole script tag -- grumble grumble... $scripts .= Skin::makeGlobalVariablesScript( $sk->getSkinName() ) . "\n"; // Script and Messages "only" diff --git a/includes/ResourceLoaderContext.php b/includes/ResourceLoaderContext.php index b97638a0d1..82ed6fd836 100644 --- a/includes/ResourceLoaderContext.php +++ b/includes/ResourceLoaderContext.php @@ -31,23 +31,24 @@ class ResourceLoaderContext { protected $language; protected $direction; protected $skin; + protected $user; protected $debug; protected $only; protected $hash; /* Methods */ - public function __construct( WebRequest $request, $server ) { + public function __construct( WebRequest $request ) { global $wgLang, $wgDefaultSkin; $this->request = $request; - $this->server = $server; // Interperet request $this->modules = explode( '|', $request->getVal( 'modules' ) ); $this->language = $request->getVal( 'lang' ); $this->direction = $request->getVal( 'dir' ); $this->skin = $request->getVal( 'skin' ); - $this->debug = $request->getVal( 'debug' ) === 'true' || $request->getBool( 'debug' ); + $this->user = $request->getVal( 'user' ); + $this->debug = $request->getBool( 'debug' ) && $request->getVal( 'debug' ) === 'true'; $this->only = $request->getVal( 'only' ); // Fallback on system defaults @@ -68,10 +69,6 @@ class ResourceLoaderContext { return $this->request; } - public function getServer() { - return $this->server; - } - public function getModules() { return $this->modules; } @@ -88,6 +85,10 @@ class ResourceLoaderContext { return $this->skin; } + public function getUser() { + return $this->skin; + } + public function getDebug() { return $this->debug; } @@ -111,6 +112,6 @@ class ResourceLoaderContext { public function getHash() { return isset( $this->hash ) ? $this->hash : $this->hash = - implode( '|', array( $this->language, $this->skin, $this->debug, $this->only ) ); + implode( '|', array( $this->language, $this->skin, $this->user, $this->debug, $this->only ) ); } } diff --git a/includes/ResourceLoaderModule.php b/includes/ResourceLoaderModule.php index 832d116ae8..2020e57e3d 100644 --- a/includes/ResourceLoaderModule.php +++ b/includes/ResourceLoaderModule.php @@ -81,8 +81,6 @@ abstract class ResourceLoaderModule { return $context->getDirection() === 'rtl'; } - /* Abstract Methods */ - /** * Get all JS for this module for a given language and skin. * Includes all relevant JS except loader scripts. @@ -90,7 +88,10 @@ abstract class ResourceLoaderModule { * @param $context ResourceLoaderContext object * @return String: JS */ - public abstract function getScript( ResourceLoaderContext $context ); + public function getScript( ResourceLoaderContext $context ) { + // Stub, override expected + return ''; + } /** * Get all CSS for this module for a given skin. @@ -98,7 +99,10 @@ abstract class ResourceLoaderModule { * @param $context ResourceLoaderContext object * @return array: strings of CSS keyed by media type */ - public abstract function getStyles( ResourceLoaderContext $context ); + public function getStyles( ResourceLoaderContext $context ) { + // Stub, override expected + return ''; + } /** * Get the messages needed for this module. @@ -107,14 +111,20 @@ abstract class ResourceLoaderModule { * * @return array of message keys. Keys may occur more than once */ - public abstract function getMessages(); + public function getMessages() { + // Stub, override expected + return array(); + } /** * Get the loader JS for this module, if set. * * @return Mixed: loader JS (string) or false if no custom loader set */ - public abstract function getLoaderScript(); + public function getLoaderScript() { + // Stub, override expected + return ''; + } /** * Get a list of modules this module depends on. @@ -131,8 +141,13 @@ abstract class ResourceLoaderModule { * loader script, see getLoaderScript() * @return Array of module names (strings) */ - public abstract function getDependencies(); + public function getDependencies() { + // Stub, override expected + return array(); + } + /* Abstract Methods */ + /** * Get this module's last modification timestamp for a given * combination of language, skin and debug mode flag. This is typically @@ -682,58 +697,65 @@ abstract class ResourceLoaderWikiModule extends ResourceLoaderModule { /* Protected Members */ // In-object cache for modified time - protected $modifiedTime = null; + protected $modifiedTime = array(); /* Abstract Protected Methods */ abstract protected function getPages( ResourceLoaderContext $context ); - /* Protected Methods */ - - protected function getStyleCode( array $styles ) { - foreach ( $styles as $media => $messages ) { - foreach ( $messages as $i => $message ) { - $style = wfMsgExt( $message, 'content' ); - if ( !wfEmptyMsg( $message, $style ) ) { - $styles[$media][$i] = $style; - } + /* Methods */ + + public function getScript( ResourceLoaderContext $context ) { + $scripts = ''; + foreach ( $this->getPages( $context ) as $page => $options ) { + if ( $options['type'] === 'script' ) { + $script = wfMsgExt( $page, 'content' ); + $scripts .= "/* MediaWiki:$page */\n" . ( !wfEmptyMsg( $page, $script ) ? $script : '' ) . "\n"; } } - foreach ( $styles as $media => $messages ) { - $styles[$media] = implode( "\n", $messages ); + return $scripts; + } + + public function getStyles( ResourceLoaderContext $context ) { + $styles = array(); + foreach ( $this->getPages( $context ) as $page => $options ) { + if ( $options['type'] === 'style' ) { + $media = isset( $options['media'] ) ? $options['media'] : 'all'; + $style = wfMsgExt( $page, 'content' ); + if ( !isset( $styles[$media] ) ) { + $styles[$media] = ''; + } + $styles[$media] .= "/* MediaWiki:$page */\n" . ( !wfEmptyMsg( $page, $style ) ? $style : '' ) . "\n"; + } } return $styles; } - - /* Methods */ - + public function getModifiedTime( ResourceLoaderContext $context ) { - if ( isset( $this->modifiedTime[$context->getHash()] ) ) { - return $this->modifiedTime[$context->getHash()]; + $hash = $context->getHash(); + if ( isset( $this->modifiedTime[$hash] ) ) { + return $this->modifiedTime[$hash]; } - $pages = $this->getPages( $context ); - foreach ( $pages as $i => $page ) { - $pages[$i] = Title::makeTitle( NS_MEDIAWIKI, $page ); + $titles = array(); + foreach ( $this->getPages( $context ) as $page => $options ) { + $titles[] = Title::makeTitle( NS_MEDIAWIKI, $page ); } // Do batch existence check // TODO: This would work better if page_touched were loaded by this as well - $lb = new LinkBatch( $pages ); + $lb = new LinkBatch( $titles ); $lb->execute(); - $this->modifiedTime = 1; // wfTimestamp() interprets 0 as "now" - foreach ( $pages as $page ) { - if ( $page->exists() ) { - $this->modifiedTime = max( $this->modifiedTime, wfTimestamp( TS_UNIX, $page->getTouched() ) ); + $modifiedTime = 1; // wfTimestamp() interprets 0 as "now" + foreach ( $titles as $title ) { + if ( $title->exists() ) { + $modifiedTime = max( $modifiedTime, wfTimestamp( TS_UNIX, $title->getTouched() ) ); } } - return $this->modifiedTime; + return $this->modifiedTime[$hash] = $modifiedTime; } - public function getMessages() { return array(); } - public function getLoaderScript() { return ''; } - public function getDependencies() { return array(); } } /** - * Custom module for site customizations + * Module for site customizations */ class ResourceLoaderSiteModule extends ResourceLoaderWikiModule { @@ -742,49 +764,172 @@ class ResourceLoaderSiteModule extends ResourceLoaderWikiModule { protected function getPages( ResourceLoaderContext $context ) { global $wgHandheldStyle; - // HACK: We duplicate the message names from generateUserJs() and generateUserCss here and weird things (i.e. - // mtime moving backwards) can happen when a MediaWiki:Something.js page is deleted $pages = array( - 'Common.js', - 'Common.css', - ucfirst( $context->getSkin() ) . '.js', - ucfirst( $context->getSkin() ) . '.css', - 'Print.css', + 'Common.js' => array( 'type' => 'script' ), + 'Common.css' => array( 'type' => 'style' ), + ucfirst( $context->getSkin() ) . '.js' => array( 'type' => 'script' ), + ucfirst( $context->getSkin() ) . '.css' => array( 'type' => 'style' ), + 'Print.css' => array( 'type' => 'style', 'media' => 'print' ), ); if ( $wgHandheldStyle ) { - $pages[] = 'Handheld.css'; + $pages['Handheld.css'] = array( 'type' => 'style', 'media' => 'handheld' ); } return $pages; } +} + +/** + * Module for user customizations + */ +class ResourceLoaderUserModule extends ResourceLoaderWikiModule { + + /* Protected Methods */ + + protected function getPages( ResourceLoaderContext $context ) { + global $wgAllowUserCss; + + if ( $context->getUser() && $wgAllowUserCss ) { + $user = User::newFromName( $context->getUser() ); + $userPage = $user->getUserPage()->getPrefixedText(); + return array( + "$userPage/common.css" => array( 'type' => 'style' ), + "$userPage/" . $context->getSkin() . '.css' => array( 'type' => 'style' ), + ); + } + return array(); + } +} + +/** + * Module for user preference customizations + */ +class ResourceLoaderUserPreferencesModule extends ResourceLoaderModule { + + /* Protected Members */ + + protected $modifiedTime = array(); /* Methods */ - public function getScript( ResourceLoaderContext $context ) { - return Skin::newFromKey( $context->getSkin() )->generateUserJs(); + public function getModifiedTime( ResourceLoaderContext $context ) { + $hash = $context->getHash(); + if ( isset( $this->modifiedTime[$hash] ) ) { + return $this->modifiedTime[$hash]; + } + $user = User::newFromName( $context->getUser() ); + return $this->modifiedTime[$hash] = $user->getTouched(); } public function getStyles( ResourceLoaderContext $context ) { - global $wgHandheldStyle; - $styles = array( - 'all' => array( 'Common.css', $context->getSkin() . '.css' ), - 'print' => array( 'Print.css' ), - ); - if ( $wgHandheldStyle ) { - $sources['handheld'] = array( 'Handheld.css' ); + global $wgAllowUserCssPrefs; + if ( $wgAllowUserCssPrefs ) { + $user = User::newFromName( $context->getUser() ); + $rules = array(); + if ( ( $underline = $user->getOption( 'underline' ) ) < 2 ) { + $rules[] = "a { text-decoration: " . ( $underline ? 'underline' : 'none' ) . "; }"; + } + if ( $user->getOption( 'highlightbroken' ) ) { + $rules[] = "a.new, #quickbar a.new { color: #CC2200; }\n"; + } else { + $rules[] = "a.new, #quickbar a.new, a.stub, #quickbar a.stub { color: inherit; }"; + $rules[] = "a.new:after, #quickbar a.new:after { content: '?'; color: #CC2200; }"; + $rules[] = "a.stub:after, #quickbar a.stub:after { content: '!'; color: #772233; }"; + } + if ( $user->getOption( 'justify' ) ) { + $rules[] = "#article, #bodyContent, #mw_content { text-align: justify; }\n"; + } + if ( !$user->getOption( 'showtoc' ) ) { + $rules[] = "#toc { display: none; }\n"; + } + if ( !$user->getOption( 'editsection' ) ) { + $rules[] = ".editsection { display: none; }\n"; + } + if ( ( $fontstyle = $user->getOption( 'editfont' ) ) !== 'default' ) { + $rules[] = "textarea { font-family: $fontstyle; }\n"; + } + return array( 'all' => implode( "\n", $rules ) ); } - return $this->getStyleCode( $styles ); + return array(); + } + + public function getFlip( $context ) { + global $wgContLang; + + return $wgContLang->getDir() !== $context->getDirection(); } } class ResourceLoaderStartUpModule extends ResourceLoaderModule { /* Protected Members */ - protected $modifiedTime = null; + protected $modifiedTime = array(); + /* Protected Methods */ + + protected function getConfig( $context ) { + global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension, $wgArticlePath, $wgScriptPath, $wgServer, + $wgContLang, $wgBreakFrames, $wgVariantArticlePath, $wgActionPaths, $wgUseAjax, $wgAjaxWatch, $wgVersion, + $wgEnableAPI, $wgEnableWriteAPI, $wgDBname, $wgEnableMWSuggest, $wgSitename, $wgFileExtensions; + + // Pre-process information + $separatorTransTable = $wgContLang->separatorTransformTable(); + $separatorTransTable = $separatorTransTable ? $separatorTransTable : array(); + $compactSeparatorTransTable = array( + implode( "\t", array_keys( $separatorTransTable ) ), + implode( "\t", $separatorTransTable ), + ); + $digitTransTable = $wgContLang->digitTransformTable(); + $digitTransTable = $digitTransTable ? $digitTransTable : array(); + $compactDigitTransTable = array( + implode( "\t", array_keys( $digitTransTable ) ), + implode( "\t", $digitTransTable ), + ); + $mainPage = Title::newMainPage(); + + // Build list of variables + $vars = array( + 'wgLoadScript' => $wgLoadScript, + 'debug' => $context->getDebug(), + 'skin' => $context->getSkin(), + 'stylepath' => $wgStylePath, + 'wgUrlProtocols' => wfUrlProtocols(), + 'wgArticlePath' => $wgArticlePath, + 'wgScriptPath' => $wgScriptPath, + 'wgScriptExtension' => $wgScriptExtension, + 'wgScript' => $wgScript, + 'wgVariantArticlePath' => $wgVariantArticlePath, + 'wgActionPaths' => $wgActionPaths, + 'wgServer' => $wgServer, + 'wgUserLanguage' => $context->getLanguage(), + 'wgContentLanguage' => $wgContLang->getCode(), + 'wgBreakFrames' => $wgBreakFrames, + 'wgVersion' => $wgVersion, + 'wgEnableAPI' => $wgEnableAPI, + 'wgEnableWriteAPI' => $wgEnableWriteAPI, + 'wgSeparatorTransformTable' => $compactSeparatorTransTable, + 'wgDigitTransformTable' => $compactDigitTransTable, + 'wgMainPageTitle' => $mainPage ? $mainPage->getPrefixedText() : null, + 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(), + 'wgNamespaceIds' => $wgContLang->getNamespaceIds(), + 'wgSiteName' => $wgSitename, + 'wgFileExtensions' => $wgFileExtensions, + ); + if ( $wgContLang->hasVariants() ) { + $vars['wgUserVariant'] = $wgContLang->getPreferredVariant(); + } + if ( $wgUseAjax && $wgEnableMWSuggest ) { + $vars['wgMWSuggestTemplate'] = SearchEngine::getMWSuggestTemplate(); + $vars['wgDBname'] = $wgDBname; + $vars['wgSearchNamespaces'] = SearchEngine::userNamespaces( $wgUser ); + } + + return $vars; + } + /* Methods */ public function getScript( ResourceLoaderContext $context ) { - global $IP; + global $IP, $wgStylePath, $wgLoadScript; $scripts = file_get_contents( "$IP/resources/startup.js" ); @@ -792,9 +937,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { // Get all module registrations $registration = ResourceLoader::getModuleRegistrations( $context ); // Build configuration - $config = FormatJson::encode( - array( 'server' => $context->getServer(), 'debug' => $context->getDebug() ) - ); + $config = FormatJson::encode( $this->getConfig( $context ) ); // Add a well-known start-up function $scripts .= "window.startUp = function() { $registration mediaWiki.config.set( $config ); };"; // Build load query for jquery and mediawiki modules @@ -814,7 +957,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { ); // Build HTML code for loading jquery and mediawiki modules - $loadScript = Html::linkedScript( $context->getServer() . "?$query" ); + $loadScript = Html::linkedScript( "$wgLoadScript?$query" ); // Add code to add jquery and mediawiki loading code; only if the current client is compatible $scripts .= "if ( isCompatible() ) { document.write( '$loadScript' ); }"; // Delete the compatible function - it's not needed anymore @@ -827,14 +970,15 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { public function getModifiedTime( ResourceLoaderContext $context ) { global $IP; - if ( !is_null( $this->modifiedTime ) ) { - return $this->modifiedTime; + $hash = $context->getHash(); + if ( isset( $this->modifiedTime[$hash] ) ) { + return $this->modifiedTime[$hash]; } - - // HACK getHighestModifiedTime() calls this function, so protect against infinite recursion - $this->modifiedTime = filemtime( "$IP/resources/startup.js" ); - $this->modifiedTime = ResourceLoader::getHighestModifiedTime( $context ); - return $this->modifiedTime; + $this->modifiedTime[$hash] = filemtime( "$IP/resources/startup.js" ); + // ATTENTION!: Because of the line above, this is not going to cause infinite recursion - think carefully + // before making changes to this code! + $this->modifiedTime[$hash] = ResourceLoader::getHighestModifiedTime( $context ); + return $this->modifiedTime[$hash]; } public function getClientMaxage() { @@ -845,14 +989,9 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule { return 300; // 5 minutes } - public function getStyles( ResourceLoaderContext $context ) { return array(); } - public function getFlip( $context ) { global $wgContLang; return $wgContLang->getDir() !== $context->getDirection(); } - public function getMessages() { return array(); } - public function getLoaderScript() { return ''; } - public function getDependencies() { return array(); } } diff --git a/includes/Skin.php b/includes/Skin.php index a461b7da53..d9b58468b6 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -357,10 +357,10 @@ class Skin extends Linker { static function makeVariablesScript( $data ) { if ( $data ) { - return Html::inlineScript( 'mediaWiki.config.set(' . json_encode( $data ) . ');' ); + return Html::inlineScript( 'mediaWiki.config.set(' . FormatJson::encode( $data ) . ');' ); } else { return ''; - } + } } /** @@ -368,50 +368,16 @@ class Skin extends Linker { * @param $skinName string Name of the skin * The odd calling convention is for backwards compatibility * @todo FIXME: Make this not depend on $wgTitle! + * + * Do not add things here which can be evaluated in ResourceLoaderStartupScript - in other words, without state. + * You will only be adding bloat to the page and causing page caches to have to be purged on configuration changes. */ static function makeGlobalVariablesScript( $skinName ) { - if ( is_array( $skinName ) ) { - # Weird back-compat stuff. - $skinName = $skinName['skinname']; - } - - global $wgScript, $wgTitle, $wgStylePath, $wgUser, $wgScriptExtension; - global $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang, $wgLang; - global $wgOut, $wgArticle; - global $wgBreakFrames, $wgRequest, $wgVariantArticlePath, $wgActionPaths; - global $wgUseAjax, $wgAjaxWatch; - global $wgVersion, $wgEnableAPI, $wgEnableWriteAPI; - global $wgRestrictionTypes; - global $wgDBname, $wgEnableMWSuggest; - global $wgSitename; - + global $wgTitle, $wgUser, $wgRequest, $wgArticle, $wgOut, $wgRestrictionTypes; + $ns = $wgTitle->getNamespace(); $nsname = MWNamespace::exists( $ns ) ? MWNamespace::getCanonicalName( $ns ) : $wgTitle->getNsText(); - $separatorTransTable = $wgContLang->separatorTransformTable(); - $separatorTransTable = $separatorTransTable ? $separatorTransTable : array(); - $compactSeparatorTransTable = array( - implode( "\t", array_keys( $separatorTransTable ) ), - implode( "\t", $separatorTransTable ), - ); - $digitTransTable = $wgContLang->digitTransformTable(); - $digitTransTable = $digitTransTable ? $digitTransTable : array(); - $compactDigitTransTable = array( - implode( "\t", array_keys( $digitTransTable ) ), - implode( "\t", $digitTransTable ), - ); - - $mainPage = Title::newMainPage(); $vars = array( - 'skin' => $skinName, - 'stylepath' => $wgStylePath, - 'wgUrlProtocols' => wfUrlProtocols(), - 'wgArticlePath' => $wgArticlePath, - 'wgScriptPath' => $wgScriptPath, - 'wgScriptExtension' => $wgScriptExtension, - 'wgScript' => $wgScript, - 'wgVariantArticlePath' => $wgVariantArticlePath, - 'wgActionPaths' => (object)$wgActionPaths, - 'wgServer' => $wgServer, 'wgCanonicalNamespace' => $nsname, 'wgCanonicalSpecialPageName' => $ns == NS_SPECIAL ? SpecialPage::resolveAlias( $wgTitle->getDBkey() ) : false, # bug 21115 @@ -423,56 +389,16 @@ class Skin extends Linker { 'wgIsArticle' => $wgOut->isArticle(), 'wgUserName' => $wgUser->isAnon() ? null : $wgUser->getName(), 'wgUserGroups' => $wgUser->getEffectiveGroups(), - 'wgUserLanguage' => $wgLang->getCode(), - 'wgContentLanguage' => $wgContLang->getCode(), - 'wgBreakFrames' => $wgBreakFrames, 'wgCurRevisionId' => isset( $wgArticle ) ? $wgArticle->getLatest() : 0, - 'wgVersion' => $wgVersion, - 'wgEnableAPI' => $wgEnableAPI, - 'wgEnableWriteAPI' => $wgEnableWriteAPI, - 'wgSeparatorTransformTable' => $compactSeparatorTransTable, - 'wgDigitTransformTable' => $compactDigitTransTable, - 'wgMainPageTitle' => $mainPage ? $mainPage->getPrefixedText() : null, - 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(), - 'wgNamespaceIds' => $wgContLang->getNamespaceIds(), - 'wgSiteName' => $wgSitename, 'wgCategories' => $wgOut->getCategories(), ); - - if ( $wgContLang->hasVariants() ) { - $vars['wgUserVariant'] = $wgContLang->getPreferredVariant(); - } - - // if on upload page output the extension list & js_upload - if ( SpecialPage::resolveAlias( $wgTitle->getDBkey() ) == 'Upload' ) { - global $wgFileExtensions; - $vars['wgFileExtensions'] = $wgFileExtensions; - } - - if ( $wgUseAjax && $wgEnableMWSuggest && !$wgUser->getOption( 'disablesuggest', false ) ) { - $vars['wgMWSuggestTemplate'] = SearchEngine::getMWSuggestTemplate(); - $vars['wgDBname'] = $wgDBname; - $vars['wgSearchNamespaces'] = SearchEngine::userNamespaces( $wgUser ); - $vars['wgMWSuggestMessages'] = array( wfMsg( 'search-mwsuggest-enabled' ), wfMsg( 'search-mwsuggest-disabled' ) ); - } - foreach ( $wgRestrictionTypes as $type ) { $vars['wgRestriction' . ucfirst( $type )] = $wgTitle->getRestrictions( $type ); } - - if ( $wgOut->isArticleRelated() && $wgUseAjax && $wgAjaxWatch && $wgUser->isLoggedIn() ) { - $msgs = (object)array(); - - foreach ( array( 'watch', 'unwatch', 'watching', 'unwatching', - 'tooltip-ca-watch', 'tooltip-ca-unwatch' ) as $msgName ) { - $msgs-> { $msgName . 'Msg' } = wfMsg( $msgName ); - } - $vars['wgAjaxWatch'] = $msgs; - } - + // Allow extensions to add their custom variables to the global JS variables wfRunHooks( 'MakeGlobalVariablesScript', array( &$vars ) ); - + return self::makeVariablesScript( $vars ); } @@ -521,51 +447,20 @@ class Skin extends Linker { * @return string */ public function generateUserJs( $skinName = null ) { - global $wgStylePath; - - wfProfileIn( __METHOD__ ); - - if ( !$skinName ) { - $skinName = $this->getSkinName(); - } - - $s = "/* generated javascript */\n"; - $s .= "var skin = '" . Xml::escapeJsString( $skinName ) . "';\n"; - $s .= "var stylepath = '" . Xml::escapeJsString( $wgStylePath ) . "';"; - $s .= "\n\n/* MediaWiki:Common.js */\n"; - - $commonJs = wfMsgExt( 'common.js', 'content' ); - - if ( !wfEmptyMsg( 'common.js', $commonJs ) ) { - $s .= $commonJs; - } - - $s .= "\n\n/* MediaWiki:" . ucfirst( $skinName ) . ".js */\n"; - - // avoid inclusion of non defined user JavaScript (with custom skins only) - // by checking for default message content - $msgKey = ucfirst( $skinName ) . '.js'; - $userJS = wfMsgExt( $msgKey, 'content' ); - - if ( !wfEmptyMsg( $msgKey, $userJS ) ) { - $s .= $userJS; - } - - wfProfileOut( __METHOD__ ); - return $s; + + // Stub - see ResourceLoaderSiteModule, CologneBlue, Simple and Standard skins override this + + return ''; } /** * Generate user stylesheet for action=raw&gen=css */ public function generateUserStylesheet() { - wfProfileIn( __METHOD__ ); - - $s = "/* generated user stylesheet */\n" . - $this->reallyGenerateUserStylesheet(); - - wfProfileOut( __METHOD__ ); - return $s; + + // Stub - see ResourceLoaderUserModule, CologneBlue, Simple and Standard skins override this + + return ''; } /** @@ -573,53 +468,10 @@ class Skin extends Linker { * Anything in here won't be generated if $wgAllowUserCssPrefs is false. */ protected function reallyGenerateUserStylesheet() { - global $wgUser; - - $s = ''; - - if ( ( $undopt = $wgUser->getOption( 'underline' ) ) < 2 ) { - $underline = $undopt ? 'underline' : 'none'; - $s .= "a { text-decoration: $underline; }\n"; - } - - if ( $wgUser->getOption( 'highlightbroken' ) ) { - $s .= "a.new, #quickbar a.new { color: #CC2200; }\n"; - } else { - $s .= <<getOption( 'justify' ) ) { - $s .= "#article, #bodyContent, #mw_content { text-align: justify; }\n"; - } - - if ( !$wgUser->getOption( 'showtoc' ) ) { - $s .= "#toc { display: none; }\n"; - } - - if ( !$wgUser->getOption( 'editsection' ) ) { - $s .= ".editsection { display: none; }\n"; - } - - $fontstyle = $wgUser->getOption( 'editfont' ); - - if ( $fontstyle !== 'default' ) { - $s .= "textarea { font-family: $fontstyle; }\n"; - } - - return $s; + + // Stub - see ResourceLoaderUserModule, CologneBlue, Simple and Standard skins override this + + return ''; } /** @@ -627,7 +479,7 @@ CSS; */ function setupUserCss( OutputPage $out ) { global $wgRequest, $wgUser; - global $wgAllowUserCss, $wgUseSiteCss, $wgSquidMaxage; + global $wgUseSiteCss, $wgAllowUserCss, $wgAllowUserCssPrefs, $wgSquidMaxage; wfProfileIn( __METHOD__ ); @@ -643,51 +495,26 @@ CSS; $out->addStyle( $url ); } - // If we use the site's dynamic CSS, throw that in, too // Per-site custom styles if ( $wgUseSiteCss ) { $out->addModuleStyles( 'site' ); } - global $wgAllowUserCssPrefs; - - if ( $wgAllowUserCssPrefs ) { - 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; - } - - // 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 ) ) { + // Per-user custom styles + if ( $wgAllowUserCss ) { + if ( $this->mTitle->isCssSubpage() && $this->userCanPreview( $wgRequest->getVal( 'action' ) ) ) { // @FIXME: properly escape the cdata! $out->addInlineStyle( $wgRequest->getText( 'wpTextbox1' ) ); } else { - $names = array( 'common', $this->getSkinName() ); - foreach ( $names as $name ) { - $out->addStyle( self::makeUrl( - $this->userpage . '/' . $name . '.css', - 'action=raw&ctype=text/css' ) - ); - } + $out->addModuleStyles( 'user' ); } } + // Per-user preference styles + if ( $wgAllowUserCssPrefs ) { + $out->addModuleStyles( 'user.preferences' ); + } + wfProfileOut( __METHOD__ ); } diff --git a/load.php b/load.php index a17e56df65..85c4f67b82 100644 --- a/load.php +++ b/load.php @@ -45,7 +45,7 @@ if ( $wgRequest->isPathInfoBad() ) { } // Respond to resource loading request -ResourceLoader::respond( new ResourceLoaderContext( $wgRequest, $wgServer . $wgScriptPath . '/load.php' ) ); +ResourceLoader::respond( new ResourceLoaderContext( $wgRequest ) ); wfProfileOut( 'load.php' ); wfLogProfilingData(); diff --git a/resources/Resources.php b/resources/Resources.php index a60ae47db0..530bfc1df4 100644 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -6,6 +6,8 @@ ResourceLoader::register( array( 'site' => new ResourceLoaderSiteModule, 'startup' => new ResourceLoaderStartUpModule, + 'user' => new ResourceLoaderUserModule, + 'user.preferences' => new ResourceLoaderUserPreferencesModule, /* Skins */ @@ -356,6 +358,7 @@ ResourceLoader::register( array( 'mediawiki.legacy.mwsuggest' => new ResourceLoaderFileModule( array( 'scripts' => 'skins/common/mwsuggest.js', 'dependencies' => 'mediawiki.legacy.wikibits', + 'messages' => array( 'search-mwsuggest-enabled', 'search-mwsuggest-disabled' ), ) ), 'mediawiki.legacy.password' => new ResourceLoaderFileModule( array( 'scripts' => 'skins/common/password.js', diff --git a/resources/mediawiki/mediawiki.js b/resources/mediawiki/mediawiki.js index 19f944c2ae..a8bc2bda43 100644 --- a/resources/mediawiki/mediawiki.js +++ b/resources/mediawiki/mediawiki.js @@ -469,7 +469,7 @@ window.mediaWiki = new ( function( $ ) { var html = ''; for ( var r = 0; r < requests.length; r++ ) { // Build out the HTML - var src = mediaWiki.config.get( 'server' ) + '?' + $.param( requests[r] ); + var src = mediaWiki.config.get( 'wgLoadScript' ) + '?' + $.param( requests[r] ); html += ''; } return html; -- 2.20.1