Major refactoring of site and user CSS, creating ResourceLoaderUserModule and Resourc...
authorTrevor Parscal <tparscal@users.mediawiki.org>
Sat, 11 Sep 2010 03:26:15 +0000 (03:26 +0000)
committerTrevor Parscal <tparscal@users.mediawiki.org>
Sat, 11 Sep 2010 03:26:15 +0000 (03:26 +0000)
includes/OutputPage.php
includes/ResourceLoaderContext.php
includes/ResourceLoaderModule.php
includes/Skin.php
load.php
resources/Resources.php
resources/mediawiki/mediawiki.js

index 93f245f..c22882b 100644 (file)
@@ -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"
index b97638a..82ed6fd 100644 (file)
@@ -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 ) );
        }
 }
index 832d116..2020e57 100644 (file)
@@ -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(); }
 }
index a461b7d..d9b5846 100644 (file)
@@ -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 .= <<<CSS
-a.new, #quickbar a.new,
-a.stub, #quickbar a.stub {
-       color: inherit;
-}
-a.new:after, #quickbar a.new:after {
-       content: "?";
-       color: #CC2200;
-}
-a.stub:after, #quickbar a.stub:after {
-       content: "!";
-       color: #772233;
-}
-CSS;
-               }
-
-               if ( $wgUser->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__ );
        }
 
index a17e56d..85c4f67 100644 (file)
--- 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();
index a60ae47..530bfc1 100644 (file)
@@ -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',
index 19f944c..a8bc2bd 100644 (file)
@@ -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 += '<script type="text/javascript" src="' + src + '"></script>';
                                        }
                                        return html;