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.
This commit is contained in:
parent
af26088bd9
commit
a99f9ec28b
7 changed files with 279 additions and 295 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,7 +141,12 @@ 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
|
||||
|
|
@ -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 */
|
||||
/* 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;
|
||||
}
|
||||
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(); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ 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,53 +389,13 @@ 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 ) );
|
||||
|
||||
|
|
@ -521,51 +447,20 @@ class Skin extends Linker {
|
|||
* @return string
|
||||
*/
|
||||
public function generateUserJs( $skinName = null ) {
|
||||
global $wgStylePath;
|
||||
|
||||
wfProfileIn( __METHOD__ );
|
||||
// Stub - see ResourceLoaderSiteModule, CologneBlue, Simple and Standard skins override this
|
||||
|
||||
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;
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate user stylesheet for action=raw&gen=css
|
||||
*/
|
||||
public function generateUserStylesheet() {
|
||||
wfProfileIn( __METHOD__ );
|
||||
|
||||
$s = "/* generated user stylesheet */\n" .
|
||||
$this->reallyGenerateUserStylesheet();
|
||||
// Stub - see ResourceLoaderUserModule, CologneBlue, Simple and Standard skins override this
|
||||
|
||||
wfProfileOut( __METHOD__ );
|
||||
return $s;
|
||||
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 = '';
|
||||
// Stub - see ResourceLoaderUserModule, CologneBlue, Simple and Standard skins override this
|
||||
|
||||
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;
|
||||
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__ );
|
||||
}
|
||||
|
||||
|
|
|
|||
2
load.php
2
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();
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue