r68446 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r68445‎ | r68446 | r68447 >
Date:08:15, 23 June 2010
Author:catrope
Status:deferred
Tags:
Comment:
resourceloader: Output styles and messages the proper way, through mw.implement(). Fix example in buildUrlString() documentation and make encode() publicly accessible as mw.util.urlencode()
Modified paths:
  • /branches/resourceloader/phase3/includes/ResourceLoader.php (modified) (history)
  • /branches/resourceloader/phase3/resources/core/mw.js (modified) (history)

Diff [purge]

Index: branches/resourceloader/phase3/includes/ResourceLoader.php
@@ -69,8 +69,6 @@
7070 ),
7171 );
7272
73 - private $scripts = array();
74 - private $styles = array();
7573 private $loadedModules = array();
7674 private $includeCore = false;
7775
@@ -94,10 +92,6 @@
9593 $this->includeCore = true;
9694 } else if ( isset( self::$modules[$module] ) ) {
9795 $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 - }
10296 } else {
10397 // We have a problem, they've asked for something we don't have!
10498 }
@@ -114,43 +108,7 @@
115109 public function setUseCSSJanus( $use ) {
116110 $this->useCSSJanus = $use;
117111 }
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 - }
136112
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 - */
155113 public function getOutput() {
156114 // Because these are keyed by module, in the case that more than one module asked for the same script only the
157115 // first will end up being registered - the client loader can't handle multiple modules per implementation yet,
@@ -181,15 +139,28 @@
182140 * Also, the naming of these variables is horrible and sad, hopefully this can be worked on
183141 */
184142
 143+ // Get messages in one go
 144+ $blobs = MessageBlobStore::get( $this->lang, $this->loadedModules );
 145+
185146 // TODO: file_get_contents() errors?
186147 // 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'] );
190154 }
 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";
191164 }
192 - $retval .= $this->getStyleJS( $this->styles );
193 - $retval .= $this->getMessagesJS( $this->loadedModules );
194165
195166 if ( $this->useJSMin ) {
196167 $retval = $this->jsMin( $retval );
@@ -217,7 +188,6 @@
218189 }
219190
220191 public function jsMin( $js ) {
221 - // TODO: Implement
222192 return JSMin::minify( $js );
223193 }
224194
@@ -237,9 +207,12 @@
238208 * Get the message blobs for a set of modules
239209 * @param $lang string Language code
240210 * @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.
242212 */
243213 public static function get( $lang, $modules ) {
 214+ if ( !count( $modules ) ) {
 215+ return array();
 216+ }
244217 // Try getting from the DB first
245218 $blobs = self::getFromDB( $lang, $modules );
246219
@@ -252,7 +225,7 @@
253226 $blobs[$module] = $blob;
254227 }
255228 }
256 - return implode( ",\n", $blobs );
 229+ return $blobs;
257230 }
258231
259232 public static function set( $lang, $module, $blob ) {
Index: branches/resourceloader/phase3/resources/core/mw.js
@@ -21,49 +21,54 @@
2222 * scheme "http"
2323 * server "www.domain.com"
2424 * path "path/to/my/file.html"
25 - * query "this=th�t?" or { 'this': 'th�t?' }
 25+ * query "this=thåt" or { 'this': 'thåt' }
2626 * fragment "place_on_the_page"
2727 *
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.
2932 */
3033 this.buildUrlString = function( components ) {
3134 var url = '';
32 - if ( typeof components['scheme'] === 'string' ) {
33 - url += components['scheme'] + '://';
 35+ if ( typeof components.scheme === 'string' ) {
 36+ url += components.scheme + '://';
3437 }
35 - if ( typeof components['server'] === 'string' ) {
36 - url += components['server'] + '/';
 38+ if ( typeof components.server === 'string' ) {
 39+ url += components.server + '/';
3740 }
38 - if ( typeof components['path'] === 'string' ) {
39 - url += components['path'];
 41+ if ( typeof components.path === 'string' ) {
 42+ url += components.path;
4043 }
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 );
4548 }
46 - if ( typeof components['fragment'] === 'string' ) {
47 - url += '#' + components['fragment'];
 49+ if ( typeof components.fragment === 'string' ) {
 50+ url += '#' + components.fragment;
4851 }
4952 return url;
5053 };
5154 /**
 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+ /**
5266 * Builds a query string from an object with key and values
5367 */
5468 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 - }
6469 if ( typeof parameters === 'object' ) {
6570 var parts = [];
6671 for ( p in parameters ) {
67 - parts[parts.length] = encode( p ) + '=' + encode( parameters[p] );
 72+ parts[parts.length] = that.urlencode( p ) + '=' + that.urlencode( parameters[p] );
6873 }
6974 return parts.join( '&' );
7075 }

Status & tagging log