r99341 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r99340‎ | r99341 | r99342 >
Date:08:33, 9 October 2011
Author:kaldari
Status:reverted (Comments)
Tags:fundraising 
Comment:
entirely new scheme to optimize banner loading - down from 1.1 seconds to 0.1 seconds - needs more testing
Modified paths:
  • /trunk/extensions/CentralNotice/CentralNotice.php (modified) (history)
  • /trunk/extensions/CentralNotice/special/SpecialBannerController.php (modified) (history)
  • /trunk/extensions/CentralNotice/special/SpecialBannerListLoader.php (modified) (history)

Diff [purge]

Index: trunk/extensions/CentralNotice/special/SpecialBannerListLoader.php
@@ -1,6 +1,7 @@
22 <?php
33
44 /**
 5+ * Note: This file is deprecated and should be deleted if the new banner loading system works better.
56 * Generates JSON files listing all the banners for a particular site
67 */
78 class SpecialBannerListLoader extends UnlistedSpecialPage {
Index: trunk/extensions/CentralNotice/special/SpecialBannerController.php
@@ -4,8 +4,8 @@
55 * Generates Javascript file which controls banner selection on the client side
66 */
77 class SpecialBannerController extends UnlistedSpecialPage {
8 - protected $sharedMaxAge = 3600; // Cache for 1 hour on the server side
9 - protected $maxAge = 3600; // Cache for 1 hour on the client side
 8+ protected $sharedMaxAge = 300; // Cache for 5 minutes on the server side
 9+ protected $maxAge = 300; // Cache for 5 minutes on the client side
1010
1111 function __construct() {
1212 // Register special page
@@ -19,16 +19,11 @@
2020 $this->sendHeaders();
2121
2222 $content = $this->getOutput();
23 - if ( strlen( $content ) == 0 ) {
24 - // Hack for IE/Mac 0-length keepalive problem, see RawPage.php
25 - echo "/* Empty */";
26 - } else {
27 - echo $content;
28 - }
 23+ echo $content;
2924 }
3025
3126 /**
32 - * Generate the HTTP response headers for the banner controller
 27+ * Generate the HTTP response headers
3328 */
3429 function sendHeaders() {
3530 global $wgJsMimeType;
@@ -45,7 +40,7 @@
4641 function getOutput() {
4742 global $wgCentralPagePath, $wgContLang;
4843
49 - $js = $this->getScriptFunctions() . $this->getToggleScripts();
 44+ $js = $this->getAllBannerLists() . $this->getScriptFunctions() . $this->getToggleScripts();
5045 $js .= <<<JAVASCRIPT
5146 ( function( $ ) {
5247 $.ajaxSetup({ cache: true });
@@ -81,22 +76,12 @@
8277 } else {
8378 var geoLocation = Geo.country; // pull the geo info
8479 }
85 - var bannerListQuery = $.param( { 'language': wgContentLanguage, 'project': wgNoticeProject, 'country': geoLocation } );
86 -JAVASCRIPT;
87 - $js .= "\n\t\t\t\tvar bannerListURL = wgScript + '?title=' + encodeURIComponent('" .
88 - $wgContLang->specialPage( 'BannerListLoader' ) .
89 - "') + '&cache=/cn.js&' + bannerListQuery;\n";
90 - $js .= <<<JAVASCRIPT
91 - var request = $.ajax( {
92 - url: bannerListURL,
93 - dataType: 'json',
94 - success: $.centralNotice.fn.chooseBanner
95 - } );
 80+ var bannerList = $.parseJSON( wgBannerList[geoLocation] );
 81+ $.centralNotice.fn.chooseBanner( bannerList );
9682 },
9783 'chooseBanner': function( bannerList ) {
9884 // Convert the json object to a true array
9985 bannerList = Array.prototype.slice.call( bannerList );
100 -
10186 // Make sure there are some banners to choose from
10287 if ( bannerList.length == 0 ) return false;
10388
@@ -137,17 +122,29 @@
138123 }
139124 }
140125 }
141 - $( document ).ready( function () {
142 - // Initialize the query string vars
143 - $.centralNotice.fn.getQueryStringVariables();
 126+ // Initialize the query string vars
 127+ $.centralNotice.fn.getQueryStringVariables();
 128+ if ( Geo.country ) {
 129+ // We know the user's country so go ahead and load everything
144130 if( $.centralNotice.data.getVars['banner'] ) {
145 - // if we're forcing one banner
 131+ // We're forcing one banner
146132 $.centralNotice.fn.loadBanner( $.centralNotice.data.getVars['banner'] );
147133 } else {
148134 // Look for banners ready to go NOW
149135 $.centralNotice.fn.loadBannerList( $.centralNotice.data.getVars['country'] );
150136 }
151 - } ); //document ready
 137+ } else {
 138+ // We don't know the user's country yet, so we have to wait for the GeoIP lookup
 139+ $( document ).ready( function () {
 140+ if( $.centralNotice.data.getVars['banner'] ) {
 141+ // We're forcing one banner
 142+ $.centralNotice.fn.loadBanner( $.centralNotice.data.getVars['banner'] );
 143+ } else {
 144+ // Look for banners ready to go NOW
 145+ $.centralNotice.fn.loadBannerList( $.centralNotice.data.getVars['country'] );
 146+ }
 147+ } ); //document ready
 148+ }
152149 } )( jQuery );
153150 JAVASCRIPT;
154151 return $js;
@@ -218,5 +215,41 @@
219216 JAVASCRIPT;
220217 return $script;
221218 }
 219+
 220+ /**
 221+ * Generate all the banner lists for all the countries
 222+ */
 223+ function getAllBannerLists() {
 224+ $script = "var wgBannerList = new Array();\r\n";
 225+ $countriesList = CentralNoticeDB::getCountriesList();
 226+ foreach ( $countriesList as $countryCode => $countryName ) {
 227+ $script .= "wgBannerList['$countryCode'] = '".$this->getBannerList( $countryCode )."';\r\n";
 228+ }
 229+ return $script;
 230+ }
 231+
 232+ /**
 233+ * Generate JSON banner list for a given country
 234+ */
 235+ function getBannerList( $country ) {
 236+ global $wgNoticeProject, $wgNoticeLang;
 237+ $banners = array();
 238+
 239+ // See if we have any preferred campaigns for this language and project
 240+ $campaigns = CentralNoticeDB::getCampaigns( $wgNoticeProject, $wgNoticeLang, null, 1, 1, $country );
 241+
 242+ // Quick short circuit to show preferred campaigns
 243+ if ( $campaigns ) {
 244+ // Pull banners
 245+ $banners = CentralNoticeDB::getCampaignBanners( $campaigns );
 246+ }
222247
 248+ // Didn't find any preferred banners so do an old style lookup
 249+ if ( !$banners ) {
 250+ $banners = CentralNoticeDB::getBannersByTarget( $wgNoticeProject, $wgNoticeLang, $country );
 251+ }
 252+
 253+ return FormatJson::encode( $banners );
 254+ }
 255+
223256 }
Index: trunk/extensions/CentralNotice/CentralNotice.php
@@ -102,9 +102,8 @@
103103
104104 if ( $wgCentralNoticeLoader ) {
105105 $wgHooks['LoadExtensionSchemaUpdates'][] = 'efCentralNoticeSchema';
106 - $wgHooks['BeforePageDisplay'][] = 'efCentralNoticeLoader';
107106 $wgHooks['MakeGlobalVariablesScript'][] = 'efCentralNoticeDefaults';
108 - $wgHooks['SiteNoticeAfter'][] = 'efCentralNoticeDisplay';
 107+ $wgHooks['SiteNoticeAfter'][] = 'efCentralNoticeLoader';
109108 $wgHooks['SkinAfterBottomScripts'][] = 'efCentralNoticeGeoLoader';
110109 }
111110
@@ -200,40 +199,38 @@
201200 return true;
202201 }
203202
204 -function efCentralNoticeLoader( $out, $skin ) {
205 - global $wgOut;
206 -
207 - // Include '.js' to exempt script from squid cache expiration override
208 - $centralLoader = SpecialPage::getTitleFor( 'BannerController' )->getLocalUrl( 'cache=/cn.js' );
209 -
210 - // Insert the banner controller Javascript into the <head>
211 - $wgOut->addScriptFile( $centralLoader );
212 -
213 - return true;
214 -}
215 -
216203 function efCentralNoticeGeoLoader( $skin, &$text ) {
217 - // Insert the geo IP lookup
218 - $text .= '<script type="text/javascript" src="//geoiplookup.wikimedia.org/"></script>';
 204+ // Insert the geo IP lookup and cookie setter
 205+ $text .= <<<HTML
 206+<script type="text/javascript" src="//geoiplookup.wikimedia.org/"></script>
 207+<script>
 208+var e = new Date();
 209+e.setTime( e.getTime() + (30*24*60*60*1000) ); // 30 days
 210+document.cookie = 'geo_country=' + Geo.country + '; expires=' + e.toGMTString() + '; path=/';
 211+</script>
 212+HTML;
219213 return true;
220214 }
221215
222216 function efCentralNoticeDefaults( &$vars ) {
223217 global $wgNoticeProject;
224 - // Initialize global Javascript variables. We initialize Geo with empty values so if the geo
225 - // IP lookup fails we don't have any surprises.
 218+ // Initialize global Javascript variables
226219 $geo = (object)array();
227220 $geo->{'city'} = '';
228 - $geo->{'country'} = '';
229 - $vars['Geo'] = $geo; // change this to wgGeo as soon as Mark updates on his end
 221+ if ( array_key_exists( 'geo_country', $_COOKIE ) && $_COOKIE['geo_country'] != '' ) {
 222+ $geo->{'country'} = $_COOKIE['geo_country'];
 223+ } else {
 224+ $geo->{'country'} = '';
 225+ }
 226+ $vars['Geo'] = $geo;
230227 $vars['wgNoticeProject'] = $wgNoticeProject;
231228 return true;
232229 }
233230
234 -function efCentralNoticeDisplay( &$notice ) {
 231+function efCentralNoticeLoader( &$notice ) {
235232 // setup siteNotice div
236 - $notice =
237 - '<!-- centralNotice loads here -->'. // hack for IE8 to collapse empty div
238 - $notice;
 233+ // Include '.js' to exempt script from squid cache expiration override
 234+ $centralLoader = SpecialPage::getTitleFor( 'BannerController' )->getLocalUrl( 'cache=/cn.js' );
 235+ $notice .= '<!-- centralNotice loads here --><script type="text/javascript" src="'.$centralLoader.'"></script>';
239236 return true;
240237 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r99383follow-up to r99341 - abstracting script calls, switching to camelcase for co...kaldari23:07, 9 October 2011
r99496reverting new banner loading scheme for now - reverts r99341 and r99383kaldari17:02, 11 October 2011
r100100MFT r92510, r92676, r96496, r97304, r99160, r99165, r99169, r99176, r99178, r...awjrichards23:56, 17 October 2011

Comments

#Comment by Nikerabbit (talk | contribs)   20:48, 9 October 2011

No Html::inlineScript?

#Comment by Kaldari (talk | contribs)   23:07, 9 October 2011

Seems like a silly thing to abstract, but fixed in r99383 :)

#Comment by Kaldari (talk | contribs)   01:04, 10 October 2011

For a full explanation of these changes, please refer to http://wikitech.wikimedia.org/view/CentralNotice/Optimizing_banner_loading

Status & tagging log