Index: trunk/phase3/maintenance/tests/phpunit/includes/ResourceLoaderTest.php |
— | — | @@ -1,6 +1,7 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | 4 | class ResourceLoaderTest extends PHPUnit_Framework_TestCase { |
| 5 | + |
5 | 6 | /* Provider Methods */ |
6 | 7 | |
7 | 8 | public function provide() { |
Index: trunk/phase3/includes/ResourceLoaderContext.php |
— | — | @@ -30,6 +30,7 @@ |
31 | 31 | |
32 | 32 | /* Protected Members */ |
33 | 33 | |
| 34 | + protected $resourceLoader; |
34 | 35 | protected $request; |
35 | 36 | protected $modules; |
36 | 37 | protected $language; |
— | — | @@ -43,9 +44,10 @@ |
44 | 45 | |
45 | 46 | /* Methods */ |
46 | 47 | |
47 | | - public function __construct( WebRequest $request ) { |
| 48 | + public function __construct( ResourceLoader $resourceLoader, WebRequest $request ) { |
48 | 49 | global $wgLang, $wgDefaultSkin, $wgResourceLoaderDebug; |
49 | 50 | |
| 51 | + $this->resourceLoader = $resourceLoader; |
50 | 52 | $this->request = $request; |
51 | 53 | // Interperet request |
52 | 54 | $this->modules = explode( '|', $request->getVal( 'modules' ) ); |
— | — | @@ -71,6 +73,10 @@ |
72 | 74 | } |
73 | 75 | } |
74 | 76 | |
| 77 | + public function getResourceLoader() { |
| 78 | + return $this->resourceLoader; |
| 79 | + } |
| 80 | + |
75 | 81 | public function getRequest() { |
76 | 82 | return $this->request; |
77 | 83 | } |
Index: trunk/phase3/includes/OutputPage.php |
— | — | @@ -25,6 +25,7 @@ |
26 | 26 | |
27 | 27 | var $mScripts = '', $mLinkColours, $mPageLinkTitle = '', $mHeadItems = array(); |
28 | 28 | var $mModules = array(), $mModuleScripts = array(), $mModuleStyles = array(), $mModuleMessages = array(); |
| 29 | + var $mResourceLoader; |
29 | 30 | var $mInlineMsg = array(); |
30 | 31 | |
31 | 32 | var $mTemplateIds = array(); |
— | — | @@ -2281,9 +2282,13 @@ |
2282 | 2283 | } |
2283 | 2284 | |
2284 | 2285 | // TODO: Document |
2285 | | - static function makeResourceLoaderLink( $skin, $modules, $only, $useESI = false ) { |
| 2286 | + protected function makeResourceLoaderLink( $skin, $modules, $only, $useESI = false ) { |
2286 | 2287 | global $wgUser, $wgLang, $wgRequest, $wgLoadScript, $wgResourceLoaderDebug, $wgResourceLoaderUseESI, |
2287 | 2288 | $wgResourceLoaderInlinePrivateModules; |
| 2289 | + // Lazy-load ResourceLoader |
| 2290 | + if ( is_null( $this->mResourceLoader ) ) { |
| 2291 | + $this->mResourceLoader = new ResourceLoader(); |
| 2292 | + } |
2288 | 2293 | // TODO: Should this be a static function of ResourceLoader instead? |
2289 | 2294 | // TODO: Divide off modules starting with "user", and add the user parameter to them |
2290 | 2295 | $query = array( |
— | — | @@ -2299,7 +2304,7 @@ |
2300 | 2305 | // Create keyed-by-group list of module objects from modules list |
2301 | 2306 | $groups = array(); |
2302 | 2307 | foreach ( (array) $modules as $name ) { |
2303 | | - $module = ResourceLoader::getModule( $name ); |
| 2308 | + $module = $this->mResourceLoader->getModule( $name ); |
2304 | 2309 | $group = $module->getGroup(); |
2305 | 2310 | if ( !isset( $groups[$group] ) ) { |
2306 | 2311 | $groups[$group] = array(); |
— | — | @@ -2315,17 +2320,17 @@ |
2316 | 2321 | } |
2317 | 2322 | // Support inlining of private modules if configured as such |
2318 | 2323 | if ( $group === 'private' && $wgResourceLoaderInlinePrivateModules ) { |
2319 | | - $context = new ResourceLoaderContext( new FauxRequest( $query ) ); |
| 2324 | + $context = new ResourceLoaderContext( $this->mResourceLoader, new FauxRequest( $query ) ); |
2320 | 2325 | if ( $only == 'styles' ) { |
2321 | 2326 | $links .= Html::inlineStyle( |
2322 | 2327 | ResourceLoader::makeLoaderConditionalScript( |
2323 | | - ResourceLoader::makeModuleResponse( $context, $modules ) |
| 2328 | + $this->mResourceLoader->makeModuleResponse( $context, $modules ) |
2324 | 2329 | ) |
2325 | 2330 | ); |
2326 | 2331 | } else { |
2327 | 2332 | $links .= Html::inlineScript( |
2328 | 2333 | ResourceLoader::makeLoaderConditionalScript( |
2329 | | - ResourceLoader::makeModuleResponse( $context, $modules ) |
| 2334 | + $this->mResourceLoader->makeModuleResponse( $context, $modules ) |
2330 | 2335 | ) |
2331 | 2336 | ); |
2332 | 2337 | } |
— | — | @@ -2336,7 +2341,7 @@ |
2337 | 2342 | // we can ensure cache misses on change |
2338 | 2343 | if ( $group === 'user' || $group === 'site' ) { |
2339 | 2344 | // Create a fake request based on the one we are about to make so modules return correct times |
2340 | | - $context = new ResourceLoaderContext( new FauxRequest( $query ) ); |
| 2345 | + $context = new ResourceLoaderContext( $this->mResourceLoader, new FauxRequest( $query ) ); |
2341 | 2346 | // Get the maximum timestamp |
2342 | 2347 | $timestamp = 0; |
2343 | 2348 | foreach ( $modules as $module ) { |
— | — | @@ -2380,7 +2385,7 @@ |
2381 | 2386 | global $wgUser, $wgRequest, $wgUseSiteJs, $wgResourceLoaderDebug; |
2382 | 2387 | |
2383 | 2388 | // Startup - this will immediately load jquery and mediawiki modules |
2384 | | - $scripts = self::makeResourceLoaderLink( $sk, 'startup', 'scripts', true ); |
| 2389 | + $scripts = $this->makeResourceLoaderLink( $sk, 'startup', 'scripts', true ); |
2385 | 2390 | |
2386 | 2391 | // Configuration -- This could be merged together with the load and go, but makeGlobalVariablesScript returns a |
2387 | 2392 | // whole script tag -- grumble grumble... |
— | — | @@ -2390,20 +2395,20 @@ |
2391 | 2396 | if ( $wgRequest->getFuzzyBool( 'debug', $wgResourceLoaderDebug ) ) { |
2392 | 2397 | // Scripts |
2393 | 2398 | foreach ( $this->getModuleScripts() as $name ) { |
2394 | | - $scripts .= self::makeResourceLoaderLink( $sk, $name, 'scripts' ); |
| 2399 | + $scripts .= $this->makeResourceLoaderLink( $sk, $name, 'scripts' ); |
2395 | 2400 | } |
2396 | 2401 | // Messages |
2397 | 2402 | foreach ( $this->getModuleMessages() as $name ) { |
2398 | | - $scripts .= self::makeResourceLoaderLink( $sk, $name, 'messages' ); |
| 2403 | + $scripts .= $this->makeResourceLoaderLink( $sk, $name, 'messages' ); |
2399 | 2404 | } |
2400 | 2405 | } else { |
2401 | 2406 | // Scripts |
2402 | 2407 | if ( count( $this->getModuleScripts() ) ) { |
2403 | | - $scripts .= self::makeResourceLoaderLink( $sk, $this->getModuleScripts(), 'scripts' ); |
| 2408 | + $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleScripts(), 'scripts' ); |
2404 | 2409 | } |
2405 | 2410 | // Messages |
2406 | 2411 | if ( count( $this->getModuleMessages() ) ) { |
2407 | | - $scripts .= self::makeResourceLoaderLink( $sk, $this->getModuleMessages(), 'messages' ); |
| 2412 | + $scripts .= $this->makeResourceLoaderLink( $sk, $this->getModuleMessages(), 'messages' ); |
2408 | 2413 | } |
2409 | 2414 | } |
2410 | 2415 | |
— | — | @@ -2423,18 +2428,18 @@ |
2424 | 2429 | # XXX: additional security check/prompt? |
2425 | 2430 | $this->addInlineScript( $wgRequest->getText( 'wpTextbox1' ) ); |
2426 | 2431 | } else { |
2427 | | - $scripts .= self::makeResourceLoaderLink( $sk, array( 'user', 'user.options' ), 'scripts' ); |
| 2432 | + $scripts .= $this->makeResourceLoaderLink( $sk, array( 'user', 'user.options' ), 'scripts' ); |
2428 | 2433 | $userOptionsAdded = true; |
2429 | 2434 | } |
2430 | 2435 | } |
2431 | 2436 | if ( !$userOptionsAdded ) { |
2432 | | - $scripts .= self::makeResourceLoaderLink( $sk, 'user.options', 'scripts' ); |
| 2437 | + $scripts .= $this->makeResourceLoaderLink( $sk, 'user.options', 'scripts' ); |
2433 | 2438 | } |
2434 | 2439 | $scripts .= "\n" . $this->mScripts; |
2435 | 2440 | |
2436 | 2441 | // Add site JS if enabled |
2437 | 2442 | if ( $wgUseSiteJs ) { |
2438 | | - $scripts .= self::makeResourceLoaderLink( $sk, 'site', 'scripts' ); |
| 2443 | + $scripts .= $this->makeResourceLoaderLink( $sk, 'site', 'scripts' ); |
2439 | 2444 | } |
2440 | 2445 | |
2441 | 2446 | return $scripts; |
— | — | @@ -2558,11 +2563,11 @@ |
2559 | 2564 | // Support individual script requests in debug mode |
2560 | 2565 | if ( $wgRequest->getFuzzyBool( 'debug', $wgResourceLoaderDebug ) ) { |
2561 | 2566 | foreach ( $this->getModuleStyles() as $name ) { |
2562 | | - $tags[] = self::makeResourceLoaderLink( $sk, $name, 'styles' ); |
| 2567 | + $tags[] = $this->makeResourceLoaderLink( $sk, $name, 'styles' ); |
2563 | 2568 | } |
2564 | 2569 | } else { |
2565 | 2570 | if ( count( $this->getModuleStyles() ) ) { |
2566 | | - $tags[] = self::makeResourceLoaderLink( $sk, $this->getModuleStyles(), 'styles' ); |
| 2571 | + $tags[] = $this->makeResourceLoaderLink( $sk, $this->getModuleStyles(), 'styles' ); |
2567 | 2572 | } |
2568 | 2573 | } |
2569 | 2574 | |
Index: trunk/phase3/includes/ResourceLoader.php |
— | — | @@ -30,30 +30,11 @@ |
31 | 31 | /* Protected Static Members */ |
32 | 32 | |
33 | 33 | // @var array list of module name/ResourceLoaderModule object pairs |
34 | | - protected static $modules = array(); |
35 | | - protected static $initialized = false; |
| 34 | + protected $modules = array(); |
36 | 35 | |
37 | | - /* Protected Static Methods */ |
38 | | - |
39 | | - /** |
40 | | - * Registers core modules and runs registration hooks |
41 | | - */ |
42 | | - protected static function initialize() { |
43 | | - global $IP; |
44 | | - |
45 | | - // Safety check - this should never be called more than once |
46 | | - if ( !self::$initialized ) { |
47 | | - wfProfileIn( __METHOD__ ); |
48 | | - // This needs to be first, because hooks might call ResourceLoader |
49 | | - // public interfaces which will call this |
50 | | - self::$initialized = true; |
51 | | - self::register( include( "$IP/resources/Resources.php" ) ); |
52 | | - wfRunHooks( 'ResourceLoaderRegisterModules' ); |
53 | | - wfProfileOut( __METHOD__ ); |
54 | | - } |
55 | | - } |
| 36 | + /* Protected Methods */ |
56 | 37 | |
57 | | - /* |
| 38 | + /** |
58 | 39 | * Loads information stored in the database about modules |
59 | 40 | * |
60 | 41 | * This is not inside the module code because it's so much more performant to request all of the information at once |
— | — | @@ -62,7 +43,7 @@ |
63 | 44 | * @param $modules array list of module names to preload information for |
64 | 45 | * @param $context ResourceLoaderContext context to load the information within |
65 | 46 | */ |
66 | | - protected static function preloadModuleInfo( array $modules, ResourceLoaderContext $context ) { |
| 47 | + protected function preloadModuleInfo( array $modules, ResourceLoaderContext $context ) { |
67 | 48 | $dbr = wfGetDb( DB_SLAVE ); |
68 | 49 | $skin = $context->getSkin(); |
69 | 50 | $lang = $context->getLanguage(); |
— | — | @@ -76,21 +57,21 @@ |
77 | 58 | |
78 | 59 | $modulesWithDeps = array(); |
79 | 60 | foreach ( $res as $row ) { |
80 | | - self::$modules[$row->md_module]->setFileDependencies( $skin, |
| 61 | + $this->modules[$row->md_module]->setFileDependencies( $skin, |
81 | 62 | FormatJson::decode( $row->md_deps, true ) |
82 | 63 | ); |
83 | 64 | $modulesWithDeps[] = $row->md_module; |
84 | 65 | } |
85 | 66 | // Register the absence of a dependencies row too |
86 | 67 | foreach ( array_diff( $modules, $modulesWithDeps ) as $name ) { |
87 | | - self::$modules[$name]->setFileDependencies( $skin, array() ); |
| 68 | + $this->modules[$name]->setFileDependencies( $skin, array() ); |
88 | 69 | } |
89 | 70 | |
90 | 71 | // Get message blob mtimes. Only do this for modules with messages |
91 | 72 | $modulesWithMessages = array(); |
92 | 73 | $modulesWithoutMessages = array(); |
93 | 74 | foreach ( $modules as $name ) { |
94 | | - if ( count( self::$modules[$name]->getMessages() ) ) { |
| 75 | + if ( count( $this->modules[$name]->getMessages() ) ) { |
95 | 76 | $modulesWithMessages[] = $name; |
96 | 77 | } else { |
97 | 78 | $modulesWithoutMessages[] = $name; |
— | — | @@ -103,11 +84,11 @@ |
104 | 85 | ), __METHOD__ |
105 | 86 | ); |
106 | 87 | foreach ( $res as $row ) { |
107 | | - self::$modules[$row->mr_resource]->setMsgBlobMtime( $lang, $row->mr_timestamp ); |
| 88 | + $this->modules[$row->mr_resource]->setMsgBlobMtime( $lang, $row->mr_timestamp ); |
108 | 89 | } |
109 | 90 | } |
110 | 91 | foreach ( $modulesWithoutMessages as $name ) { |
111 | | - self::$modules[$name]->setMsgBlobMtime( $lang, 0 ); |
| 92 | + $this->modules[$name]->setMsgBlobMtime( $lang, 0 ); |
112 | 93 | } |
113 | 94 | } |
114 | 95 | |
— | — | @@ -119,7 +100,7 @@ |
120 | 101 | * @param $file String: path to file being filtered, (optional: only required for CSS to resolve paths) |
121 | 102 | * @return String: filtered data |
122 | 103 | */ |
123 | | - protected static function filter( $filter, $data ) { |
| 104 | + protected function filter( $filter, $data ) { |
124 | 105 | global $wgMemc; |
125 | 106 | wfProfileIn( __METHOD__ ); |
126 | 107 | |
— | — | @@ -166,9 +147,25 @@ |
167 | 148 | return $result; |
168 | 149 | } |
169 | 150 | |
170 | | - /* Static Methods */ |
| 151 | + /* Methods */ |
171 | 152 | |
172 | 153 | /** |
| 154 | + * Registers core modules and runs registration hooks |
| 155 | + */ |
| 156 | + public function __construct() { |
| 157 | + global $IP; |
| 158 | + |
| 159 | + wfProfileIn( __METHOD__ ); |
| 160 | + |
| 161 | + // Register core modules |
| 162 | + $this->register( include( "$IP/resources/Resources.php" ) ); |
| 163 | + // Register extension modules |
| 164 | + wfRunHooks( 'ResourceLoaderRegisterModules', array( &$this ) ); |
| 165 | + |
| 166 | + wfProfileOut( __METHOD__ ); |
| 167 | + } |
| 168 | + |
| 169 | + /** |
173 | 170 | * Registers a module with the ResourceLoader system. |
174 | 171 | * |
175 | 172 | * Note that registering the same object under multiple names is not supported |
— | — | @@ -184,14 +181,13 @@ |
185 | 182 | * happened, but in bringing errors to the client in a way that they can |
186 | 183 | * easily see them if they want to, such as by using FireBug |
187 | 184 | */ |
188 | | - public static function register( $name, ResourceLoaderModule $object = null ) { |
| 185 | + public function register( $name, ResourceLoaderModule $object = null ) { |
189 | 186 | wfProfileIn( __METHOD__ ); |
190 | | - self::initialize(); |
191 | 187 | |
192 | 188 | // Allow multiple modules to be registered in one call |
193 | 189 | if ( is_array( $name ) && !isset( $object ) ) { |
194 | 190 | foreach ( $name as $key => $value ) { |
195 | | - self::register( $key, $value ); |
| 191 | + $this->register( $key, $value ); |
196 | 192 | } |
197 | 193 | |
198 | 194 | wfProfileOut( __METHOD__ ); |
— | — | @@ -199,13 +195,14 @@ |
200 | 196 | } |
201 | 197 | |
202 | 198 | // Disallow duplicate registrations |
203 | | - if ( isset( self::$modules[$name] ) ) { |
| 199 | + if ( isset( $this->modules[$name] ) ) { |
204 | 200 | // A module has already been registered by this name |
205 | 201 | throw new MWException( 'Another module has already been registered as ' . $name ); |
206 | 202 | } |
207 | 203 | // Attach module |
208 | | - self::$modules[$name] = $object; |
| 204 | + $this->modules[$name] = $object; |
209 | 205 | $object->setName( $name ); |
| 206 | + |
210 | 207 | wfProfileOut( __METHOD__ ); |
211 | 208 | } |
212 | 209 | |
— | — | @@ -214,11 +211,8 @@ |
215 | 212 | * |
216 | 213 | * @return Array: array( modulename => ResourceLoaderModule ) |
217 | 214 | */ |
218 | | - public static function getModules() { |
219 | | - |
220 | | - self::initialize(); |
221 | | - |
222 | | - return self::$modules; |
| 215 | + public function getModules() { |
| 216 | + return $this->modules; |
223 | 217 | } |
224 | 218 | |
225 | 219 | /** |
— | — | @@ -227,51 +221,27 @@ |
228 | 222 | * @param $name String: module name |
229 | 223 | * @return mixed ResourceLoaderModule or null if not registered |
230 | 224 | */ |
231 | | - public static function getModule( $name ) { |
232 | | - |
233 | | - self::initialize(); |
234 | | - |
235 | | - return isset( self::$modules[$name] ) ? self::$modules[$name] : null; |
| 225 | + public function getModule( $name ) { |
| 226 | + return isset( $this->modules[$name] ) ? $this->modules[$name] : null; |
236 | 227 | } |
237 | 228 | |
238 | 229 | /** |
239 | | - * Get the highest modification time of all modules, based on a given |
240 | | - * combination of language code, skin name and debug mode flag. |
241 | | - * |
242 | | - * @param $context ResourceLoaderContext object |
243 | | - * @return Integer: UNIX timestamp |
244 | | - */ |
245 | | - public static function getHighestModifiedTime( ResourceLoaderContext $context ) { |
246 | | - |
247 | | - self::initialize(); |
248 | | - |
249 | | - $time = 1; // wfTimestamp() treats 0 as 'now', so that's not a suitable choice |
250 | | - |
251 | | - foreach ( self::$modules as $module ) { |
252 | | - $time = max( $time, $module->getModifiedTime( $context ) ); |
253 | | - } |
254 | | - |
255 | | - return $time; |
256 | | - } |
257 | | - |
258 | | - /** |
259 | 230 | * Outputs a response to a resource load-request, including a content-type header |
260 | 231 | * |
261 | 232 | * @param $context ResourceLoaderContext object |
262 | 233 | */ |
263 | | - public static function respond( ResourceLoaderContext $context ) { |
| 234 | + public function respond( ResourceLoaderContext $context ) { |
264 | 235 | global $wgResourceLoaderMaxage; |
265 | 236 | |
266 | 237 | wfProfileIn( __METHOD__ ); |
267 | | - self::initialize(); |
268 | 238 | |
269 | 239 | // Split requested modules into two groups, modules and missing |
270 | 240 | $modules = array(); |
271 | 241 | $missing = array(); |
272 | 242 | |
273 | 243 | foreach ( $context->getModules() as $name ) { |
274 | | - if ( isset( self::$modules[$name] ) ) { |
275 | | - $modules[$name] = self::$modules[$name]; |
| 244 | + if ( isset( $this->modules[$name] ) ) { |
| 245 | + $modules[$name] = $this->modules[$name]; |
276 | 246 | } else { |
277 | 247 | $missing[] = $name; |
278 | 248 | } |
— | — | @@ -291,7 +261,7 @@ |
292 | 262 | } |
293 | 263 | |
294 | 264 | // Preload information needed to the mtime calculation below |
295 | | - self::preloadModuleInfo( array_keys( $modules ), $context ); |
| 265 | + $this->preloadModuleInfo( array_keys( $modules ), $context ); |
296 | 266 | |
297 | 267 | // To send Last-Modified and support If-Modified-Since, we need to detect |
298 | 268 | // the last modified time |
— | — | @@ -326,10 +296,10 @@ |
327 | 297 | wfProfileOut( __METHOD__ ); |
328 | 298 | } |
329 | 299 | |
330 | | - public static function makeModuleResponse( ResourceLoaderContext $context, array $modules, $missing = null ) { |
| 300 | + public function makeModuleResponse( ResourceLoaderContext $context, array $modules, $missing = null ) { |
331 | 301 | // Pre-fetch blobs |
332 | 302 | $blobs = $context->shouldIncludeMessages() ? |
333 | | - MessageBlobStore::get( array_keys( $modules ), $context->getLanguage() ) : array(); |
| 303 | + MessageBlobStore::get( $modules, $context->getLanguage() ) : array(); |
334 | 304 | |
335 | 305 | // Generate output |
336 | 306 | $out = ''; |
— | — | @@ -349,9 +319,9 @@ |
350 | 320 | ( count( $styles = $module->getStyles( $context ) ) ) |
351 | 321 | ) { |
352 | 322 | // Flip CSS on a per-module basis |
353 | | - if ( self::$modules[$name]->getFlip( $context ) ) { |
| 323 | + if ( $this->modules[$name]->getFlip( $context ) ) { |
354 | 324 | foreach ( $styles as $media => $style ) { |
355 | | - $styles[$media] = self::filter( 'flip-css', $style ); |
| 325 | + $styles[$media] = $this->filter( 'flip-css', $style ); |
356 | 326 | } |
357 | 327 | } |
358 | 328 | } |
— | — | @@ -374,7 +344,7 @@ |
375 | 345 | // Minify CSS before embedding in mediaWiki.loader.implement call (unless in debug mode) |
376 | 346 | if ( !$context->getDebug() ) { |
377 | 347 | foreach ( $styles as $media => $style ) { |
378 | | - $styles[$media] = self::filter( 'minify-css', $style ); |
| 348 | + $styles[$media] = $this->filter( 'minify-css', $style ); |
379 | 349 | } |
380 | 350 | } |
381 | 351 | $out .= self::makeLoaderImplementScript( $name, $scripts, $styles, $messages ); |
— | — | @@ -400,14 +370,14 @@ |
401 | 371 | return $out; |
402 | 372 | } else { |
403 | 373 | if ( $context->getOnly() === 'styles' ) { |
404 | | - return self::filter( 'minify-css', $out ); |
| 374 | + return $this->filter( 'minify-css', $out ); |
405 | 375 | } else { |
406 | | - return self::filter( 'minify-js', $out ); |
| 376 | + return $this->filter( 'minify-js', $out ); |
407 | 377 | } |
408 | 378 | } |
409 | 379 | } |
410 | 380 | |
411 | | - // Client code generation methods |
| 381 | + /* Static Methods */ |
412 | 382 | |
413 | 383 | public static function makeLoaderImplementScript( $name, $scripts, $styles, $messages ) { |
414 | 384 | if ( is_array( $scripts ) ) { |
Index: trunk/phase3/includes/MessageBlobStore.php |
— | — | @@ -31,7 +31,7 @@ |
32 | 32 | class MessageBlobStore { |
33 | 33 | /** |
34 | 34 | * Get the message blobs for a set of modules |
35 | | - * @param $modules array Array of module names |
| 35 | + * @param $modules array Array of module objects keyed by module name |
36 | 36 | * @param $lang string Language code |
37 | 37 | * @return array An array mapping module names to message blobs |
38 | 38 | */ |
— | — | @@ -43,14 +43,14 @@ |
44 | 44 | return array(); |
45 | 45 | } |
46 | 46 | // Try getting from the DB first |
47 | | - $blobs = self::getFromDB( $modules, $lang ); |
| 47 | + $blobs = self::getFromDB( array_keys( $modules ), $lang ); |
48 | 48 | |
49 | 49 | // Generate blobs for any missing modules and store them in the DB |
50 | | - $missing = array_diff( $modules, array_keys( $blobs ) ); |
51 | | - foreach ( $missing as $module ) { |
52 | | - $blob = self::insertMessageBlob( $module, $lang ); |
| 50 | + $missing = array_diff( array_keys( $modules ), array_keys( $blobs ) ); |
| 51 | + foreach ( $missing as $name ) { |
| 52 | + $blob = self::insertMessageBlob( $name, $modules[$name], $lang ); |
53 | 53 | if ( $blob ) { |
54 | | - $blobs[$module] = $blob; |
| 54 | + $blobs[$name] = $blob; |
55 | 55 | } |
56 | 56 | } |
57 | 57 | |
— | — | @@ -66,8 +66,8 @@ |
67 | 67 | * @param $lang string Language code |
68 | 68 | * @return mixed Message blob or false if the module has no messages |
69 | 69 | */ |
70 | | - public static function insertMessageBlob( $module, $lang ) { |
71 | | - $blob = self::generateMessageBlob( $module, $lang ); |
| 70 | + public static function insertMessageBlob( $name, ResourceLoaderModule $module, $lang ) { |
| 71 | + $blob = self::generateMessageBlob( $name, $module, $lang ); |
72 | 72 | |
73 | 73 | if ( !$blob ) { |
74 | 74 | return false; |
— | — | @@ -76,7 +76,7 @@ |
77 | 77 | $dbw = wfGetDB( DB_MASTER ); |
78 | 78 | $success = $dbw->insert( 'msg_resource', array( |
79 | 79 | 'mr_lang' => $lang, |
80 | | - 'mr_resource' => $module, |
| 80 | + 'mr_resource' => $name, |
81 | 81 | 'mr_blob' => $blob, |
82 | 82 | 'mr_timestamp' => $dbw->timestamp() |
83 | 83 | ), |
— | — | @@ -88,7 +88,7 @@ |
89 | 89 | if ( $dbw->affectedRows() == 0 ) { |
90 | 90 | // Blob was already present, fetch it |
91 | 91 | $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array( |
92 | | - 'mr_resource' => $module, |
| 92 | + 'mr_resource' => $name, |
93 | 93 | 'mr_lang' => $lang, |
94 | 94 | ), |
95 | 95 | __METHOD__ |
— | — | @@ -96,11 +96,10 @@ |
97 | 97 | } else { |
98 | 98 | // Update msg_resource_links |
99 | 99 | $rows = array(); |
100 | | - $mod = ResourceLoader::getModule( $module ); |
101 | 100 | |
102 | | - foreach ( $mod->getMessages() as $key ) { |
| 101 | + foreach ( $module->getMessages() as $key ) { |
103 | 102 | $rows[] = array( |
104 | | - 'mrl_resource' => $module, |
| 103 | + 'mrl_resource' => $name, |
105 | 104 | 'mrl_message' => $key |
106 | 105 | ); |
107 | 106 | } |
— | — | @@ -120,14 +119,14 @@ |
121 | 120 | * @return mixed If $lang is set, the new message blob for that language is |
122 | 121 | * returned if present. Otherwise, null is returned. |
123 | 122 | */ |
124 | | - public static function updateModule( $module, $lang = null ) { |
| 123 | + public static function updateModule( $name, ResourceLoaderModule $module, $lang = null ) { |
125 | 124 | $retval = null; |
126 | 125 | |
127 | 126 | // Find all existing blobs for this module |
128 | 127 | $dbw = wfGetDB( DB_MASTER ); |
129 | 128 | $res = $dbw->select( 'msg_resource', |
130 | 129 | array( 'mr_lang', 'mr_blob' ), |
131 | | - array( 'mr_resource' => $module ), |
| 130 | + array( 'mr_resource' => $name ), |
132 | 131 | __METHOD__ |
133 | 132 | ); |
134 | 133 | |
— | — | @@ -139,13 +138,13 @@ |
140 | 139 | |
141 | 140 | foreach ( $res as $row ) { |
142 | 141 | $oldBlob = $row->mr_blob; |
143 | | - $newBlob = self::generateMessageBlob( $module, $row->mr_lang ); |
| 142 | + $newBlob = self::generateMessageBlob( $name, $module, $row->mr_lang ); |
144 | 143 | |
145 | 144 | if ( $row->mr_lang === $lang ) { |
146 | 145 | $retval = $newBlob; |
147 | 146 | } |
148 | 147 | $newRows[] = array( |
149 | | - 'mr_resource' => $module, |
| 148 | + 'mr_resource' => $name, |
150 | 149 | 'mr_lang' => $row->mr_lang, |
151 | 150 | 'mr_blob' => $newBlob, |
152 | 151 | 'mr_timestamp' => $now |
— | — | @@ -166,7 +165,7 @@ |
167 | 166 | // Delete removed messages, insert added ones |
168 | 167 | if ( $removed ) { |
169 | 168 | $dbw->delete( 'msg_resource_links', array( |
170 | | - 'mrl_resource' => $module, |
| 169 | + 'mrl_resource' => $name, |
171 | 170 | 'mrl_message' => $removed |
172 | 171 | ), __METHOD__ |
173 | 172 | ); |
— | — | @@ -176,7 +175,7 @@ |
177 | 176 | |
178 | 177 | foreach ( $added as $message ) { |
179 | 178 | $newLinksRows[] = array( |
180 | | - 'mrl_resource' => $module, |
| 179 | + 'mrl_resource' => $name, |
181 | 180 | 'mrl_message' => $message |
182 | 181 | ); |
183 | 182 | } |
— | — | @@ -343,11 +342,10 @@ |
344 | 343 | * @param $lang string Language code |
345 | 344 | * @return string JSON object |
346 | 345 | */ |
347 | | - private static function generateMessageBlob( $module, $lang ) { |
348 | | - $mod = ResourceLoader::getModule( $module ); |
| 346 | + private static function generateMessageBlob( $name, ResourceLoaderModule $module, $lang ) { |
349 | 347 | $messages = array(); |
350 | 348 | |
351 | | - foreach ( $mod->getMessages() as $key ) { |
| 349 | + foreach ( $module->getMessages() as $key ) { |
352 | 350 | $messages[$key] = wfMsgExt( $key, array( 'language' => $lang ) ); |
353 | 351 | } |
354 | 352 | |
Index: trunk/phase3/includes/ResourceLoaderModule.php |
— | — | @@ -1054,7 +1054,7 @@ |
1055 | 1055 | |
1056 | 1056 | $out = ''; |
1057 | 1057 | $registrations = array(); |
1058 | | - foreach ( ResourceLoader::getModules() as $name => $module ) { |
| 1058 | + foreach ( $context->getResourceLoader()->getModules() as $name => $module ) { |
1059 | 1059 | // Support module loader scripts |
1060 | 1060 | if ( ( $loader = $module->getLoaderScript() ) !== false ) { |
1061 | 1061 | $deps = FormatJson::encode( $module->getDependencies() ); |
— | — | @@ -1104,8 +1104,8 @@ |
1105 | 1105 | 'skin' => $context->getSkin(), |
1106 | 1106 | 'debug' => $context->getDebug() ? 'true' : 'false', |
1107 | 1107 | 'version' => wfTimestamp( TS_ISO_8601, round( max( |
1108 | | - ResourceLoader::getModule( 'jquery' )->getModifiedTime( $context ), |
1109 | | - ResourceLoader::getModule( 'mediawiki' )->getModifiedTime( $context ) |
| 1108 | + $context->getResourceLoader()->getModule( 'jquery' )->getModifiedTime( $context ), |
| 1109 | + $context->getResourceLoader()->getModule( 'mediawiki' )->getModifiedTime( $context ) |
1110 | 1110 | ), -2 ) ) |
1111 | 1111 | ); |
1112 | 1112 | // Ensure uniform query order |
— | — | @@ -1132,10 +1132,14 @@ |
1133 | 1133 | return $this->modifiedTime[$hash]; |
1134 | 1134 | } |
1135 | 1135 | $this->modifiedTime[$hash] = filemtime( "$IP/resources/startup.js" ); |
1136 | | - |
| 1136 | + |
1137 | 1137 | // ATTENTION!: Because of the line above, this is not going to cause infinite recursion - think carefully |
1138 | 1138 | // before making changes to this code! |
1139 | | - return $this->modifiedTime[$hash] = ResourceLoader::getHighestModifiedTime( $context ); |
| 1139 | + $time = 1; // wfTimestamp() treats 0 as 'now', so that's not a suitable choice |
| 1140 | + foreach ( $context->getResourceLoader()->getModules() as $module ) { |
| 1141 | + $time = max( $time, $module->getModifiedTime( $context ) ); |
| 1142 | + } |
| 1143 | + return $this->modifiedTime[$hash] = $time; |
1140 | 1144 | } |
1141 | 1145 | |
1142 | 1146 | public function getFlip( $context ) { |
Index: trunk/phase3/load.php |
— | — | @@ -45,7 +45,8 @@ |
46 | 46 | } |
47 | 47 | |
48 | 48 | // Respond to resource loading request |
49 | | -ResourceLoader::respond( new ResourceLoaderContext( $wgRequest ) ); |
| 49 | +$resourceLoader = new ResourceLoader(); |
| 50 | +$resourceLoader->respond( new ResourceLoaderContext( $resourceLoader, $wgRequest ) ); |
50 | 51 | |
51 | 52 | wfProfileOut( 'load.php' ); |
52 | 53 | wfLogProfilingData(); |
Index: trunk/extensions/WikiEditor/WikiEditor.hooks.php |
— | — | @@ -687,9 +687,9 @@ |
688 | 688 | * |
689 | 689 | * Adds modules to ResourceLoader |
690 | 690 | */ |
691 | | - public static function resourceLoaderRegisterModules() { |
| 691 | + public static function resourceLoaderRegisterModules( &$resourceLoader ) { |
692 | 692 | foreach ( self::$modules as $name => $resources ) { |
693 | | - ResourceLoader::register( $name, new ResourceLoaderFileModule( $resources ) ); |
| 693 | + $resourceLoader->register( $name, new ResourceLoaderFileModule( $resources ) ); |
694 | 694 | } |
695 | 695 | return true; |
696 | 696 | } |
Index: trunk/extensions/Vector/Vector.hooks.php |
— | — | @@ -212,9 +212,9 @@ |
213 | 213 | * |
214 | 214 | * Adds modules to ResourceLoader |
215 | 215 | */ |
216 | | - public static function resourceLoaderRegisterModules() { |
| 216 | + public static function resourceLoaderRegisterModules( &$resourceLoader ) { |
217 | 217 | foreach ( self::$modules as $name => $resources ) { |
218 | | - ResourceLoader::register( $name, new ResourceLoaderFileModule( $resources ) ); |
| 218 | + $resourceLoader->register( $name, new ResourceLoaderFileModule( $resources ) ); |
219 | 219 | } |
220 | 220 | return true; |
221 | 221 | } |
Index: trunk/extensions/ProofreadPage/ProofreadPage_body.php |
— | — | @@ -71,8 +71,8 @@ |
72 | 72 | |
73 | 73 | } |
74 | 74 | |
75 | | - public static function resourceLoaderRegisterModules() { |
76 | | - ResourceLoader::register( |
| 75 | + public static function resourceLoaderRegisterModules( &$resourceLoader ) { |
| 76 | + $resourceLoader->register( |
77 | 77 | 'ext.proofreadpage.page', |
78 | 78 | new ResourceLoaderFileModule( |
79 | 79 | array( |
— | — | @@ -93,7 +93,7 @@ |
94 | 94 | ) |
95 | 95 | ); |
96 | 96 | |
97 | | - ResourceLoader::register( |
| 97 | + $resourceLoader->register( |
98 | 98 | 'ext.proofreadpage.article', |
99 | 99 | new ResourceLoaderFileModule( |
100 | 100 | array( |
— | — | @@ -102,7 +102,7 @@ |
103 | 103 | ) |
104 | 104 | ); |
105 | 105 | |
106 | | - ResourceLoader::register( |
| 106 | + $resourceLoader->register( |
107 | 107 | 'ext.proofreadpage.index', |
108 | 108 | new ResourceLoaderFileModule( array( 'scripts' => 'extensions/ProofreadPage/proofread_index.js' ) ) |
109 | 109 | ); |
Index: trunk/extensions/ArticleEmblems/ArticleEmblems.hooks.php |
— | — | @@ -84,8 +84,8 @@ |
85 | 85 | /* |
86 | 86 | * ResourceLoaderRegisterModules hook |
87 | 87 | */ |
88 | | - public static function resourceLoaderRegisterModules() { |
89 | | - ResourceLoader::register( |
| 88 | + public static function resourceLoaderRegisterModules( &$resourceLoader ) { |
| 89 | + $resourceLoader->register( |
90 | 90 | 'ext.articleEmblems', |
91 | 91 | new ResourceLoaderFileModule( array( |
92 | 92 | 'styles' => 'extensions/ArticleEmblems/modules/ext.articleEmblems.css', |
Index: trunk/extensions/ClickTracking/ClickTracking.hooks.php |
— | — | @@ -71,8 +71,8 @@ |
72 | 72 | * |
73 | 73 | * Adds modules to ResourceLoader |
74 | 74 | */ |
75 | | - public static function resourceLoaderRegisterModules() { |
76 | | - ResourceLoader::register( array( |
| 75 | + public static function resourceLoaderRegisterModules( &$resourceLoader ) { |
| 76 | + $resourceLoader->register( array( |
77 | 77 | 'jquery.clickTracking' => new ResourceLoaderFileModule( array( |
78 | 78 | 'scripts' => 'extensions/ClickTracking/modules/jquery.clickTracking.js', |
79 | 79 | 'dependencies' => 'jquery.cookie', |
Index: trunk/extensions/PrefSwitch/PrefSwitch.hooks.php |
— | — | @@ -83,9 +83,9 @@ |
84 | 84 | /* |
85 | 85 | * ResourceLoaderRegisterModules hook |
86 | 86 | */ |
87 | | - public static function resourceLoaderRegisterModules() { |
| 87 | + public static function resourceLoaderRegisterModules( &$resourceLoader ) { |
88 | 88 | foreach ( self::$modules as $name => $resources ) { |
89 | | - ResourceLoader::register( $name, new ResourceLoaderFileModule( $resources ) ); |
| 89 | + $resourceLoader->register( $name, new ResourceLoaderFileModule( $resources ) ); |
90 | 90 | } |
91 | 91 | return true; |
92 | 92 | } |
Index: trunk/extensions/Translate/Translate.php |
— | — | @@ -411,8 +411,8 @@ |
412 | 412 | |
413 | 413 | |
414 | 414 | # Startup code |
415 | | -function efTranslateResources() { |
416 | | - ResourceLoader::register( array( 'translate-css' => |
| 415 | +function efTranslateResources( &$resourceLoader ) { |
| 416 | + $resourceLoader->register( array( 'translate-css' => |
417 | 417 | new ResourceLoaderFileModule( array( 'styles' => 'extensions/Translate/Translate.css' ) ) |
418 | 418 | ) ); |
419 | 419 | return true; |