Index: branches/resourceloader/phase3/includes/ResourceLoaderContext.php |
— | — | @@ -24,6 +24,8 @@ |
25 | 25 | */ |
26 | 26 | class ResourceLoaderContext { |
27 | 27 | |
| 28 | + /* Protected Members */ |
| 29 | + |
28 | 30 | protected $request; |
29 | 31 | protected $server; |
30 | 32 | protected $modules; |
— | — | @@ -32,7 +34,10 @@ |
33 | 35 | protected $skin; |
34 | 36 | protected $debug; |
35 | 37 | protected $only; |
| 38 | + protected $hash; |
36 | 39 | |
| 40 | + /* Methods */ |
| 41 | + |
37 | 42 | public function __construct( WebRequest $request, $server ) { |
38 | 43 | global $wgUser, $wgLang, $wgDefaultSkin; |
39 | 44 | |
— | — | @@ -56,37 +61,53 @@ |
57 | 62 | $this->skin = $wgDefaultSkin; |
58 | 63 | } |
59 | 64 | } |
| 65 | + |
60 | 66 | public function getRequest() { |
61 | 67 | return $this->request; |
62 | 68 | } |
| 69 | + |
63 | 70 | public function getServer() { |
64 | 71 | return $this->server; |
65 | 72 | } |
| 73 | + |
66 | 74 | public function getModules() { |
67 | 75 | return $this->modules; |
68 | 76 | } |
| 77 | + |
69 | 78 | public function getLanguage() { |
70 | 79 | return $this->language; |
71 | 80 | } |
| 81 | + |
72 | 82 | public function getDirection() { |
73 | 83 | return $this->direction; |
74 | 84 | } |
| 85 | + |
75 | 86 | public function getSkin() { |
76 | 87 | return $this->skin; |
77 | 88 | } |
| 89 | + |
78 | 90 | public function getDebug() { |
79 | 91 | return $this->debug; |
80 | 92 | } |
| 93 | + |
81 | 94 | public function getOnly() { |
82 | 95 | return $this->only; |
83 | 96 | } |
| 97 | + |
84 | 98 | public function shouldIncludeScripts() { |
85 | 99 | return is_null( $this->only ) || $this->only === 'scripts'; |
86 | 100 | } |
| 101 | + |
87 | 102 | public function shouldIncludeStyles() { |
88 | 103 | return is_null( $this->only ) || $this->only === 'styles'; |
89 | 104 | } |
| 105 | + |
90 | 106 | public function shouldIncludeMessages() { |
91 | 107 | return is_null( $this->only ) || $this->only === 'messages'; |
92 | 108 | } |
| 109 | + |
| 110 | + public function getHash() { |
| 111 | + return isset( $this->hash ) ? |
| 112 | + $this->hash : $this->hash = implode( '|', array( $this->language, $this->skin, $this->debug ) ); |
| 113 | + } |
93 | 114 | } |
\ No newline at end of file |
Index: branches/resourceloader/phase3/includes/ResourceLoader.php |
— | — | @@ -218,6 +218,8 @@ |
219 | 219 | return $time; |
220 | 220 | } |
221 | 221 | |
| 222 | + /* Methods */ |
| 223 | + |
222 | 224 | /* |
223 | 225 | * Outputs a response to a resource load-request, including a content-type header |
224 | 226 | * |
— | — | @@ -280,38 +282,6 @@ |
281 | 283 | $scripts = ''; |
282 | 284 | if ( $context->shouldIncludeScripts() ) { |
283 | 285 | $scripts .= self::$modules[$name]->getScript( $context ); |
284 | | - // Special meta-information for the 'startup' module |
285 | | - if ( $name === 'startup' && $context->getOnly() === 'scripts' ) { |
286 | | - // Get all module registrations |
287 | | - $registration = self::getModuleRegistrations( $context ); |
288 | | - // Build configuration |
289 | | - $config = FormatJson::encode( |
290 | | - array( 'server' => $context->getServer(), 'debug' => $context->getDebug() ) |
291 | | - ); |
292 | | - // Add a well-known start-up function |
293 | | - $scripts .= "window.startUp = function() { $registration mediaWiki.config.set( $config ); };"; |
294 | | - // Build load query for jquery and mediawiki modules |
295 | | - $query = wfArrayToCGI( |
296 | | - array( |
297 | | - 'modules' => implode( '|', array( 'jquery', 'mediawiki' ) ), |
298 | | - 'only' => 'scripts', |
299 | | - 'lang' => $context->getLanguage(), |
300 | | - 'dir' => $context->getDirection(), |
301 | | - 'skin' => $context->getSkin(), |
302 | | - 'debug' => $context->getDebug(), |
303 | | - 'version' => wfTimestamp( TS_ISO_8601, round( max( |
304 | | - self::$modules['jquery']->getModifiedTime( $context ), |
305 | | - self::$modules['mediawiki']->getModifiedTime( $context ) |
306 | | - ), -2 ) ) |
307 | | - ) |
308 | | - ); |
309 | | - // Build HTML code for loading jquery and mediawiki modules |
310 | | - $loadScript = Html::linkedScript( $context->getServer() . "?$query" ); |
311 | | - // Add code to add jquery and mediawiki loading code; only if the current client is compatible |
312 | | - $scripts .= "if ( isCompatible() ) { document.write( '$loadScript' ); }"; |
313 | | - // Delete the compatible function - it's not needed anymore |
314 | | - $scripts .= "delete window['isCompatible'];"; |
315 | | - } |
316 | 286 | } |
317 | 287 | // Styles |
318 | 288 | $styles = ''; |
— | — | @@ -335,7 +305,7 @@ |
336 | 306 | echo "mediaWiki.msg.set( $messages );\n"; |
337 | 307 | } else { |
338 | 308 | $styles = Xml::escapeJsString( $styles ); |
339 | | - echo "mediaWiki.loader.implement( '{$name}', function() {{$scripts}},\n'{$styles}',\n{$messages} );\n"; |
| 309 | + echo "mediaWiki.loader.implement( '$name', function() {{$scripts}},\n'$styles',\n$messages );\n"; |
340 | 310 | } |
341 | 311 | } |
342 | 312 | // Update the status of script-only modules |
— | — | @@ -345,12 +315,12 @@ |
346 | 316 | $statuses[$name] = 'ready'; |
347 | 317 | } |
348 | 318 | $statuses = FormatJson::encode( $statuses ); |
349 | | - echo "mediaWiki.loader.state( {$statuses} );"; |
| 319 | + echo "mediaWiki.loader.state( $statuses );"; |
350 | 320 | } |
351 | 321 | // Register missing modules |
352 | 322 | if ( $context->shouldIncludeScripts() ) { |
353 | 323 | foreach ( $missing as $name ) { |
354 | | - echo "mediaWiki.loader.register( '{$name}', null, 'missing' );\n"; |
| 324 | + echo "mediaWiki.loader.register( '$name', null, 'missing' );\n"; |
355 | 325 | } |
356 | 326 | } |
357 | 327 | // Output the appropriate header |
Index: branches/resourceloader/phase3/includes/ResourceLoaderModule.php |
— | — | @@ -22,8 +22,13 @@ |
23 | 23 | * Interface for resource loader modules, with name registration and maxage functionality. |
24 | 24 | */ |
25 | 25 | abstract class ResourceLoaderModule { |
26 | | - private $name = null; |
27 | 26 | |
| 27 | + /* Protected Members */ |
| 28 | + |
| 29 | + protected $name = null; |
| 30 | + |
| 31 | + /* Methods */ |
| 32 | + |
28 | 33 | /** |
29 | 34 | * Get this module's name. This is set when the module is registered |
30 | 35 | * with ResourceLoader::register() |
— | — | @@ -130,23 +135,26 @@ |
131 | 136 | * Module based on local JS/CSS files. This is the most common type of module. |
132 | 137 | */ |
133 | 138 | class ResourceLoaderFileModule extends ResourceLoaderModule { |
134 | | - private $scripts = array(); |
135 | | - private $styles = array(); |
136 | | - private $messages = array(); |
137 | | - private $dependencies = array(); |
138 | | - private $debugScripts = array(); |
139 | | - private $languageScripts = array(); |
140 | | - private $skinScripts = array(); |
141 | | - private $skinStyles = array(); |
142 | | - private $loaders = array(); |
143 | | - private $parameters = array(); |
144 | 139 | |
| 140 | + /* Protected Members */ |
| 141 | + |
| 142 | + protected $scripts = array(); |
| 143 | + protected $styles = array(); |
| 144 | + protected $messages = array(); |
| 145 | + protected $dependencies = array(); |
| 146 | + protected $debugScripts = array(); |
| 147 | + protected $languageScripts = array(); |
| 148 | + protected $skinScripts = array(); |
| 149 | + protected $skinStyles = array(); |
| 150 | + protected $loaders = array(); |
| 151 | + protected $parameters = array(); |
| 152 | + |
145 | 153 | // In-object cache for file dependencies |
146 | | - private $fileDeps = array(); |
| 154 | + protected $fileDeps = array(); |
147 | 155 | // In-object cache for mtime |
148 | | - private $modifiedTime = array(); |
| 156 | + protected $modifiedTime = array(); |
149 | 157 | |
150 | | - /* Public methods */ |
| 158 | + /* Methods */ |
151 | 159 | |
152 | 160 | /** |
153 | 161 | * Construct a new module from an options array. |
— | — | @@ -384,9 +392,8 @@ |
385 | 393 | * @return int UNIX timestamp |
386 | 394 | */ |
387 | 395 | public function getModifiedTime( ResourceLoaderContext $context ) { |
388 | | - $hash = implode( '|', array( $context->getLanguage(), $context->getSkin(), $context->getDebug() ) ); |
389 | | - if ( isset( $this->modifiedTime[$hash] ) ) { |
390 | | - return $this->modifiedTime[$hash]; |
| 396 | + if ( isset( $this->modifiedTime[$context->getHash()] ) ) { |
| 397 | + return $this->modifiedTime[$context->getHash()]; |
391 | 398 | } |
392 | 399 | |
393 | 400 | $files = array_merge( |
— | — | @@ -400,12 +407,14 @@ |
401 | 408 | $this->loaders, |
402 | 409 | $this->getFileDependencies( $context->getSkin() ) |
403 | 410 | ); |
404 | | - $this->modifiedTime[$hash] = max( |
| 411 | + $this->modifiedTime[$context->getHash()] = max( |
405 | 412 | array_map( 'filemtime', array_map( array( __CLASS__, 'remapFilename' ), $files ) ) |
406 | 413 | ); |
407 | | - return $this->modifiedTime[$hash]; |
| 414 | + return $this->modifiedTime[$context->getHash()]; |
408 | 415 | } |
409 | 416 | |
| 417 | + /* Protected Members */ |
| 418 | + |
410 | 419 | /** |
411 | 420 | * Get the primary JS for this module. This is pulled from the |
412 | 421 | * script files added through addScripts() |
— | — | @@ -558,17 +567,21 @@ |
559 | 568 | * TODO: Add Site CSS functionality too |
560 | 569 | */ |
561 | 570 | class ResourceLoaderSiteModule extends ResourceLoaderModule { |
| 571 | + |
| 572 | + /* Protected Members */ |
| 573 | + |
562 | 574 | // In-object cache for modified time |
563 | | - private $modifiedTime = null; |
| 575 | + protected $modifiedTime = null; |
564 | 576 | |
| 577 | + /* Methods */ |
| 578 | + |
565 | 579 | public function getScript( ResourceLoaderContext $context ) { |
566 | 580 | return Skin::newFromKey( $context->getSkin() )->generateUserJs(); |
567 | 581 | } |
568 | 582 | |
569 | 583 | public function getModifiedTime( ResourceLoaderContext $context ) { |
570 | | - $hash = implode( '|', array( $context->getLanguage(), $context->getSkin(), $context->getDebug() ) ); |
571 | | - if ( isset( $this->modifiedTime[$hash] ) ) { |
572 | | - return $this->modifiedTime[$hash]; |
| 584 | + if ( isset( $this->modifiedTime[$context->getHash()] ) ) { |
| 585 | + return $this->modifiedTime[$context->getHash()]; |
573 | 586 | } |
574 | 587 | |
575 | 588 | // HACK: We duplicate the message names from generateUserJs() |
— | — | @@ -600,11 +613,49 @@ |
601 | 614 | |
602 | 615 | |
603 | 616 | class ResourceLoaderStartUpModule extends ResourceLoaderModule { |
604 | | - private $modifiedTime = null; |
605 | 617 | |
| 618 | + /* Protected Members */ |
| 619 | + |
| 620 | + protected $modifiedTime = null; |
| 621 | + |
| 622 | + /* Methods */ |
| 623 | + |
606 | 624 | public function getScript( ResourceLoaderContext $context ) { |
607 | 625 | global $IP; |
608 | | - return file_get_contents( "$IP/resources/startup.js" ); |
| 626 | + |
| 627 | + $scripts = file_get_contents( "$IP/resources/startup.js" ); |
| 628 | + if ( $context->getOnly() === 'scripts' ) { |
| 629 | + // Get all module registrations |
| 630 | + $registration = ResourceLoader::getModuleRegistrations( $context ); |
| 631 | + // Build configuration |
| 632 | + $config = FormatJson::encode( |
| 633 | + array( 'server' => $context->getServer(), 'debug' => $context->getDebug() ) |
| 634 | + ); |
| 635 | + // Add a well-known start-up function |
| 636 | + $scripts .= "window.startUp = function() { $registration mediaWiki.config.set( $config ); };"; |
| 637 | + // Build load query for jquery and mediawiki modules |
| 638 | + $query = wfArrayToCGI( |
| 639 | + array( |
| 640 | + 'modules' => implode( '|', array( 'jquery', 'mediawiki' ) ), |
| 641 | + 'only' => 'scripts', |
| 642 | + 'lang' => $context->getLanguage(), |
| 643 | + 'dir' => $context->getDirection(), |
| 644 | + 'skin' => $context->getSkin(), |
| 645 | + 'debug' => $context->getDebug(), |
| 646 | + 'version' => wfTimestamp( TS_ISO_8601, round( max( |
| 647 | + ResourceLoader::getModule( 'jquery' )->getModifiedTime( $context ), |
| 648 | + ResourceLoader::getModule( 'mediawiki' )->getModifiedTime( $context ) |
| 649 | + ), -2 ) ) |
| 650 | + ) |
| 651 | + ); |
| 652 | + // Build HTML code for loading jquery and mediawiki modules |
| 653 | + $loadScript = Html::linkedScript( $context->getServer() . "?$query" ); |
| 654 | + // Add code to add jquery and mediawiki loading code; only if the current client is compatible |
| 655 | + $scripts .= "if ( isCompatible() ) { document.write( '$loadScript' ); }"; |
| 656 | + // Delete the compatible function - it's not needed anymore |
| 657 | + $scripts .= "delete window['isCompatible'];"; |
| 658 | + } |
| 659 | + return $scripts; |
609 | 660 | } |
610 | 661 | |
611 | 662 | public function getModifiedTime( ResourceLoaderContext $context ) { |