Index: branches/resourceloader/phase3/includes/ResourceLoader.php |
— | — | @@ -69,8 +69,6 @@ |
70 | 70 | ), |
71 | 71 | ); |
72 | 72 | |
73 | | - private $scripts = array(); |
74 | | - private $styles = array(); |
75 | 73 | private $loadedModules = array(); |
76 | 74 | private $includeCore = false; |
77 | 75 | |
— | — | @@ -94,10 +92,6 @@ |
95 | 93 | $this->includeCore = true; |
96 | 94 | } else if ( isset( self::$modules[$module] ) ) { |
97 | 95 | $this->loadedModules[] = $module; |
98 | | - $this->scripts[$module] = self::$modules[$module]['script']; |
99 | | - if ( isset( self::$modules[$module]['style'] ) ) { |
100 | | - $this->styles[$module] = self::$modules[$module]['script']; |
101 | | - } |
102 | 96 | } else { |
103 | 97 | // We have a problem, they've asked for something we don't have! |
104 | 98 | } |
— | — | @@ -114,43 +108,7 @@ |
115 | 109 | public function setUseCSSJanus( $use ) { |
116 | 110 | $this->useCSSJanus = $use; |
117 | 111 | } |
118 | | - |
119 | | - private function getStyleJS( $styles ) { |
120 | | - $retval = ''; |
121 | | - foreach ( $styles as $style ) { |
122 | | - // TODO: file_get_contents() errors? |
123 | | - // TODO: CACHING! |
124 | | - $css = file_get_contents( $style ); |
125 | | - if ( $this->useCSSJanus ) { |
126 | | - $css = $this->cssJanus( $css ); |
127 | | - } |
128 | | - if ( $this->useCSSMin ) { |
129 | | - $css = $this->cssMin( $css ); |
130 | | - } |
131 | | - $escCss = Xml::escapeJsString( $css ); |
132 | | - $retval .= "\$j( 'head' ).append( '<style>$escCSS</style>' );\n"; |
133 | | - } |
134 | | - return $retval; |
135 | | - } |
136 | 112 | |
137 | | - private function getMessagesJS( $modules ) { |
138 | | - /* |
139 | | - $blobs = array(); |
140 | | - $dbr = wfGetDB( DB_SLAVE ); |
141 | | - $res = $dbr->select( 'msg_resource', 'msg_blob', |
142 | | - array( 'msg_resource' => $modules, 'msg_lang' => $this->lang ), |
143 | | - __METHOD__ |
144 | | - ); |
145 | | - foreach ( $res as $row ) { |
146 | | - $blobs[] = $row->msg_blob; |
147 | | - } |
148 | | - return "mw.addMessages( {\n" . implode( ",\n", $blobs ) . "\n} );"; |
149 | | - */ |
150 | | - } |
151 | | - |
152 | | - /* |
153 | | - * TODO: Might think about using an output buffer here, these string concatenations are dealing with many KB of data |
154 | | - */ |
155 | 113 | public function getOutput() { |
156 | 114 | // Because these are keyed by module, in the case that more than one module asked for the same script only the |
157 | 115 | // first will end up being registered - the client loader can't handle multiple modules per implementation yet, |
— | — | @@ -181,15 +139,28 @@ |
182 | 140 | * Also, the naming of these variables is horrible and sad, hopefully this can be worked on |
183 | 141 | */ |
184 | 142 | |
| 143 | + // Get messages in one go |
| 144 | + $blobs = MessageBlobStore::get( $this->lang, $this->loadedModules ); |
| 145 | + |
185 | 146 | // TODO: file_get_contents() errors? |
186 | 147 | // TODO: CACHING! |
187 | | - foreach ( $this->scripts as $module => $script ) { |
188 | | - if ( file_exists( $script ) ) { |
189 | | - $retval .= "mw.loader.implement( '{$module}', function() { " . file_get_contents( $script ) . " } );\n"; |
| 148 | + foreach ( $this->loadedModules as $module ) { |
| 149 | + $mod = self::$modules[$module]; |
| 150 | + $script = $style = ''; |
| 151 | + $messages = isset( $blobs[$module] ) ? $blobs[$module] : ''; |
| 152 | + if ( file_exists( $mod['script'] ) ) { |
| 153 | + $script = file_get_contents( $mod['script'] ); |
190 | 154 | } |
| 155 | + if ( isset( $mod['style'] ) && file_exists( $mod['style'] ) ) { |
| 156 | + $style = file_get_contents( $mod['style'] ); |
| 157 | + if ( $this->useCSSJanus ) { |
| 158 | + $css = $this->cssJanus( $style ); |
| 159 | + } |
| 160 | + $style = Xml::escapeJsString( $css ); |
| 161 | + } |
| 162 | + |
| 163 | + $retval .= "mw.loader.implement( '$module', function() { $script }, '$style', { $messages } );\n"; |
191 | 164 | } |
192 | | - $retval .= $this->getStyleJS( $this->styles ); |
193 | | - $retval .= $this->getMessagesJS( $this->loadedModules ); |
194 | 165 | |
195 | 166 | if ( $this->useJSMin ) { |
196 | 167 | $retval = $this->jsMin( $retval ); |
— | — | @@ -217,7 +188,6 @@ |
218 | 189 | } |
219 | 190 | |
220 | 191 | public function jsMin( $js ) { |
221 | | - // TODO: Implement |
222 | 192 | return JSMin::minify( $js ); |
223 | 193 | } |
224 | 194 | |
— | — | @@ -237,9 +207,12 @@ |
238 | 208 | * Get the message blobs for a set of modules |
239 | 209 | * @param $lang string Language code |
240 | 210 | * @param $modules array Array of module names |
241 | | - * @return array An array of incomplete JSON objects (i.e. without the {} ) with messages keys and their values. |
| 211 | + * @return array An array of incomplete JSON objects (i.e. without the {} ) containing messages keys and their values. Array keys are module names. |
242 | 212 | */ |
243 | 213 | public static function get( $lang, $modules ) { |
| 214 | + if ( !count( $modules ) ) { |
| 215 | + return array(); |
| 216 | + } |
244 | 217 | // Try getting from the DB first |
245 | 218 | $blobs = self::getFromDB( $lang, $modules ); |
246 | 219 | |
— | — | @@ -252,7 +225,7 @@ |
253 | 226 | $blobs[$module] = $blob; |
254 | 227 | } |
255 | 228 | } |
256 | | - return implode( ",\n", $blobs ); |
| 229 | + return $blobs; |
257 | 230 | } |
258 | 231 | |
259 | 232 | public static function set( $lang, $module, $blob ) { |
Index: branches/resourceloader/phase3/resources/core/mw.js |
— | — | @@ -21,49 +21,54 @@ |
22 | 22 | * scheme "http" |
23 | 23 | * server "www.domain.com" |
24 | 24 | * path "path/to/my/file.html" |
25 | | - * query "this=th�t?" or { 'this': 'th�t?' } |
| 25 | + * query "this=thåt" or { 'this': 'thåt' } |
26 | 26 | * fragment "place_on_the_page" |
27 | 27 | * |
28 | | - * Results in: "http://www.domain.com/path/to/my/file.html?this=th%E5t#place_on_the_page" |
| 28 | + * Results in: "http://www.domain.com/path/to/my/file.html?this=th%C3%A5t#place_on_the_page" |
| 29 | + * |
| 30 | + * All arguments to this function are assumed to be URL-encoded already, except for the |
| 31 | + * query parameter if provided in object form. |
29 | 32 | */ |
30 | 33 | this.buildUrlString = function( components ) { |
31 | 34 | var url = ''; |
32 | | - if ( typeof components['scheme'] === 'string' ) { |
33 | | - url += components['scheme'] + '://'; |
| 35 | + if ( typeof components.scheme === 'string' ) { |
| 36 | + url += components.scheme + '://'; |
34 | 37 | } |
35 | | - if ( typeof components['server'] === 'string' ) { |
36 | | - url += components['server'] + '/'; |
| 38 | + if ( typeof components.server === 'string' ) { |
| 39 | + url += components.server + '/'; |
37 | 40 | } |
38 | | - if ( typeof components['path'] === 'string' ) { |
39 | | - url += components['path']; |
| 41 | + if ( typeof components.path === 'string' ) { |
| 42 | + url += components.path; |
40 | 43 | } |
41 | | - if ( typeof components['query'] === 'string' ) { |
42 | | - url += '?' + components['query']; |
43 | | - } else if ( typeof components['query'] === 'object' ) { |
44 | | - url += '?' + that.buildQueryString( components['query'] ); |
| 44 | + if ( typeof components.query === 'string' ) { |
| 45 | + url += '?' + components.query; |
| 46 | + } else if ( typeof components.query === 'object' ) { |
| 47 | + url += '?' + that.buildQueryString( components.query ); |
45 | 48 | } |
46 | | - if ( typeof components['fragment'] === 'string' ) { |
47 | | - url += '#' + components['fragment']; |
| 49 | + if ( typeof components.fragment === 'string' ) { |
| 50 | + url += '#' + components.fragment; |
48 | 51 | } |
49 | 52 | return url; |
50 | 53 | }; |
51 | 54 | /** |
| 55 | + * RFC 3986 compliant URI component encoder |
| 56 | + */ |
| 57 | + this.urlencode = function( string ) { |
| 58 | + return encodeURIComponent( string ) |
| 59 | + .replace(/!/g, '%21') |
| 60 | + .replace(/'/g, '%27') |
| 61 | + .replace(/\(/g, '%28') |
| 62 | + .replace(/\)/g, '%29') |
| 63 | + .replace(/\*/g, '%2A'); |
| 64 | + } |
| 65 | + /** |
52 | 66 | * Builds a query string from an object with key and values |
53 | 67 | */ |
54 | 68 | this.buildQueryString = function( parameters ) { |
55 | | - // RFC 3986 compliant URI component encoder |
56 | | - function encode( string ) { |
57 | | - return encodeURIComponent( string ) |
58 | | - .replace(/!/g, '%21') |
59 | | - .replace(/'/g, '%27') |
60 | | - .replace(/\(/g, '%28') |
61 | | - .replace(/\)/g, '%29') |
62 | | - .replace(/\*/g, '%2A'); |
63 | | - } |
64 | 69 | if ( typeof parameters === 'object' ) { |
65 | 70 | var parts = []; |
66 | 71 | for ( p in parameters ) { |
67 | | - parts[parts.length] = encode( p ) + '=' + encode( parameters[p] ); |
| 72 | + parts[parts.length] = that.urlencode( p ) + '=' + that.urlencode( parameters[p] ); |
68 | 73 | } |
69 | 74 | return parts.join( '&' ); |
70 | 75 | } |