Index: branches/wmf/1.17wmf1/includes/OutputPage.php |
— | — | @@ -228,12 +228,37 @@ |
229 | 229 | } |
230 | 230 | |
231 | 231 | /** |
| 232 | + * Filter an array of modules to remove modules |
| 233 | + * which are no longer registered (eg a page is cached before an extension is disabled) |
| 234 | + * @param $modules Array |
| 235 | + * @param $position String if not null, only return modules with this position |
| 236 | + * @return Array |
| 237 | + */ |
| 238 | + protected function filterModules( $modules, $position = null ){ |
| 239 | + $resourceLoader = $this->getResourceLoader(); |
| 240 | + $filteredModules = array(); |
| 241 | + foreach( $modules as $val ){ |
| 242 | + $module = $resourceLoader->getModule( $val ); |
| 243 | + if( $module instanceof ResourceLoaderModule |
| 244 | + && ( is_null( $position ) || $module->getPosition() == $position ) ) |
| 245 | + { |
| 246 | + $filteredModules[] = $val; |
| 247 | + } |
| 248 | + } |
| 249 | + return $filteredModules; |
| 250 | + } |
| 251 | + |
| 252 | + /** |
232 | 253 | * Get the list of modules to include on this page |
233 | 254 | * |
| 255 | + * @param $position String if not null, only return modules with this position |
234 | 256 | * @return Array of module names |
235 | 257 | */ |
236 | | - public function getModules() { |
237 | | - return array_values( array_unique( $this->mModules ) ); |
| 258 | + public function getModules( $filter = false, $position = null, $param = 'mModules' ) { |
| 259 | + $modules = array_values( array_unique( $this->$param ) ); |
| 260 | + return $filter |
| 261 | + ? $this->filterModules( $modules, $position ) |
| 262 | + : $modules; |
238 | 263 | } |
239 | 264 | |
240 | 265 | /** |
— | — | @@ -251,8 +276,8 @@ |
252 | 277 | * Get the list of module JS to include on this page |
253 | 278 | * @return array of module names |
254 | 279 | */ |
255 | | - public function getModuleScripts() { |
256 | | - return array_values( array_unique( $this->mModuleScripts ) ); |
| 280 | + public function getModuleScripts( $filter = false, $position = null ) { |
| 281 | + return $this->getModules( $filter, $position, 'mModuleScripts' ); |
257 | 282 | } |
258 | 283 | |
259 | 284 | /** |
— | — | @@ -271,8 +296,8 @@ |
272 | 297 | * |
273 | 298 | * @return Array of module names |
274 | 299 | */ |
275 | | - public function getModuleStyles() { |
276 | | - return array_values( array_unique( $this->mModuleStyles ) ); |
| 300 | + public function getModuleStyles( $filter = false, $position = null ) { |
| 301 | + return $this->getModules( $filter, $position, 'mModuleStyles' ); |
277 | 302 | } |
278 | 303 | |
279 | 304 | /** |
— | — | @@ -291,8 +316,8 @@ |
292 | 317 | * |
293 | 318 | * @return Array of module names |
294 | 319 | */ |
295 | | - public function getModuleMessages() { |
296 | | - return array_values( array_unique( $this->mModuleMessages ) ); |
| 320 | + public function getModuleMessages( $filter = false, $position = null ) { |
| 321 | + return $this->getModules( $filter, $position, 'mModuleMessages' ); |
297 | 322 | } |
298 | 323 | |
299 | 324 | /** |
— | — | @@ -2257,6 +2282,7 @@ |
2258 | 2283 | $ret .= implode( "\n", array( |
2259 | 2284 | $this->getHeadLinks( $sk ), |
2260 | 2285 | $this->buildCssLinks( $sk ), |
| 2286 | + $this->getHeadScripts( $sk ), |
2261 | 2287 | $this->getHeadItems() |
2262 | 2288 | ) ); |
2263 | 2289 | |
— | — | @@ -2458,32 +2484,59 @@ |
2459 | 2485 | } |
2460 | 2486 | |
2461 | 2487 | /** |
2462 | | - * Gets the global variables and mScripts; also adds userjs to the end if |
2463 | | - * enabled. Despite the name, these scripts are no longer put in the |
2464 | | - * <head> but at the bottom of the <body> |
| 2488 | + * JS stuff to put in the <head>. This is the startup module, config |
| 2489 | + * vars and modules marked with position 'top' |
2465 | 2490 | * |
2466 | 2491 | * @param $sk Skin object to use |
2467 | 2492 | * @return String: HTML fragment |
2468 | 2493 | */ |
2469 | 2494 | function getHeadScripts( Skin $sk ) { |
2470 | | - global $wgUser, $wgRequest, $wgUseSiteJs; |
2471 | | - |
2472 | 2495 | // Startup - this will immediately load jquery and mediawiki modules |
2473 | 2496 | $scripts = $this->makeResourceLoaderLink( $sk, 'startup', 'scripts', true ); |
2474 | | - |
2475 | | - // Configuration -- This could be merged together with the load and go, but |
2476 | | - // makeGlobalVariablesScript returns a whole script tag -- grumble grumble... |
| 2497 | + |
| 2498 | + // Load config before anything else |
2477 | 2499 | $scripts .= Skin::makeGlobalVariablesScript( $sk->getSkinName() ) . "\n"; |
| 2500 | + |
| 2501 | + // Script and Messages "only" requests marked for top inclusion |
| 2502 | + // Messages should go first |
| 2503 | + $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleMessages( true, 'top' ), 'messages' ); |
| 2504 | + $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleScripts( true, 'top' ), 'scripts' ); |
2478 | 2505 | |
2479 | | - // Script and Messages "only" requests |
2480 | | - $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleScripts(), 'scripts' ); |
2481 | | - $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleMessages(), 'messages' ); |
| 2506 | + // Modules requests - let the client calculate dependencies and batch requests as it likes |
| 2507 | + // Only load modules that have marked themselves for loading at the top |
| 2508 | + $modules = $this->getModules( true, 'top' ); |
| 2509 | + if ( $modules ) { |
| 2510 | + $scripts .= Html::inlineScript( |
| 2511 | + ResourceLoader::makeLoaderConditionalScript( |
| 2512 | + Xml::encodeJsCall( 'mediaWiki.loader.load', array( $modules ) ) . |
| 2513 | + Xml::encodeJsCall( 'mediaWiki.loader.go', array() ) |
| 2514 | + ) |
| 2515 | + ) . "\n"; |
| 2516 | + } |
2482 | 2517 | |
| 2518 | + return $scripts; |
| 2519 | + } |
| 2520 | + |
| 2521 | + /** |
| 2522 | + * JS stuff to put at the bottom of the <body>: modules marked with position 'bottom', |
| 2523 | + * legacy scripts ($this->mScripts), user preferences, site JS and user JS |
| 2524 | + */ |
| 2525 | + function getBottomScripts( Skin $sk ) { |
| 2526 | + global $wgUseSiteJs, $wgAllowUserJs, $wgUser, $wgRequest; |
| 2527 | + |
| 2528 | + // Script and Messages "only" requests marked for bottom inclusion |
| 2529 | + // Messages should go first |
| 2530 | + $scripts = $this->makeResourceLoaderLink( $sk, $this->getModuleMessages( true, 'bottom' ), 'messages' ); |
| 2531 | + $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleScripts( true, 'bottom' ), 'scripts' ); |
| 2532 | + |
2483 | 2533 | // Modules requests - let the client calculate dependencies and batch requests as it likes |
2484 | | - if ( $this->getModules() ) { |
| 2534 | + // Only load modules that have marked themselves for loading at the bottom |
| 2535 | + $modules = $this->getModules( true, 'bottom' ); |
| 2536 | + if ( $modules ) { |
2485 | 2537 | $scripts .= Html::inlineScript( |
2486 | 2538 | ResourceLoader::makeLoaderConditionalScript( |
2487 | | - Xml::encodeJsCall( 'mediaWiki.loader.load', array( $this->getModules() ) ) . |
| 2539 | + Xml::encodeJsCall( 'mediaWiki.loader.load', array( $modules ) ) . |
| 2540 | + // the go() call is unnecessary if we inserted top modules, but we don't know for sure that we did |
2488 | 2541 | Xml::encodeJsCall( 'mediaWiki.loader.go', array() ) |
2489 | 2542 | ) |
2490 | 2543 | ) . "\n"; |
Property changes on: branches/wmf/1.17wmf1/includes/OutputPage.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
2491 | 2544 | Merged /trunk/phase3/includes/OutputPage.php:r85616-85617 |
Index: branches/wmf/1.17wmf1/includes/resourceloader/ResourceLoaderFileModule.php |
— | — | @@ -78,6 +78,8 @@ |
79 | 79 | protected $messages = array(); |
80 | 80 | /** String: Name of group to load this module in */ |
81 | 81 | protected $group; |
| 82 | + /** String: Position on the page to load this module at */ |
| 83 | + protected $position = 'bottom'; |
82 | 84 | /** Boolean: Link to raw files in debug mode */ |
83 | 85 | protected $debugRaw = true; |
84 | 86 | /** |
— | — | @@ -137,6 +139,8 @@ |
138 | 140 | * 'messages' => [array of message key strings], |
139 | 141 | * // Group which this module should be loaded together with |
140 | 142 | * 'group' => [group name string], |
| 143 | + * // Position on the page to load this module at |
| 144 | + * 'position' => ['bottom' (default) or 'top'] |
141 | 145 | * ) |
142 | 146 | */ |
143 | 147 | public function __construct( $options = array(), $localBasePath = null, |
— | — | @@ -187,6 +191,7 @@ |
188 | 192 | break; |
189 | 193 | // Single strings |
190 | 194 | case 'group': |
| 195 | + case 'position': |
191 | 196 | case 'localBasePath': |
192 | 197 | case 'remoteBasePath': |
193 | 198 | $this->{$member} = (string) $option; |
— | — | @@ -293,6 +298,10 @@ |
294 | 299 | public function getGroup() { |
295 | 300 | return $this->group; |
296 | 301 | } |
| 302 | + |
| 303 | + public function getPosition() { |
| 304 | + return $this->position; |
| 305 | + } |
297 | 306 | |
298 | 307 | /** |
299 | 308 | * Gets list of names of modules this module depends on. |
Index: branches/wmf/1.17wmf1/includes/resourceloader/ResourceLoaderModule.php |
— | — | @@ -107,6 +107,15 @@ |
108 | 108 | // Stub, override expected |
109 | 109 | return null; |
110 | 110 | } |
| 111 | + |
| 112 | + /** |
| 113 | + * Where on the HTML page should this module's JS be loaded? |
| 114 | + * 'top': in the <head> |
| 115 | + * 'bottom': at the bottom of the <body> |
| 116 | + */ |
| 117 | + public function getPosition() { |
| 118 | + return 'bottom'; |
| 119 | + } |
111 | 120 | |
112 | 121 | /** |
113 | 122 | * Get the loader JS for this module, if set. |
Property changes on: branches/wmf/1.17wmf1/includes/resourceloader/ResourceLoaderModule.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
114 | 123 | Merged /trunk/phase3/includes/resourceloader/ResourceLoaderModule.php:r85616-85617 |
Index: branches/wmf/1.17wmf1/includes/Skin.php |
— | — | @@ -928,7 +928,10 @@ |
929 | 929 | * @return String HTML-wrapped JS code to be put before </body> |
930 | 930 | */ |
931 | 931 | function bottomScripts( $out ) { |
932 | | - $bottomScriptText = "\n" . $out->getHeadScripts( $this ); |
| 932 | + // TODO and the suckage continues. This function is really just a wrapper around |
| 933 | + // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned |
| 934 | + // up at some point |
| 935 | + $bottomScriptText = $out->getBottomScripts( $this ); |
933 | 936 | wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) ); |
934 | 937 | |
935 | 938 | return $bottomScriptText; |
Property changes on: branches/wmf/1.17wmf1/includes/Skin.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
936 | 939 | Merged /trunk/phase3/includes/Skin.php:r85616-85617 |
Index: branches/wmf/1.17wmf1/resources/Resources.php |
— | — | @@ -454,6 +454,7 @@ |
455 | 455 | 'remoteBasePath' => $GLOBALS['wgStylePath'], |
456 | 456 | 'localBasePath' => "{$GLOBALS['IP']}/skins", |
457 | 457 | 'dependencies' => 'mediawiki.legacy.wikibits', |
| 458 | + 'position' => 'top', |
458 | 459 | ), |
459 | 460 | 'mediawiki.legacy.edit' => array( |
460 | 461 | 'scripts' => 'common/edit.js', |
Property changes on: branches/wmf/1.17wmf1/resources/Resources.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
461 | 462 | Merged /trunk/phase3/resources/Resources.php:r85616-85617 |