r108571 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r108570‎ | r108571 | r108572 >
Date:00:07, 11 January 2012
Author:preilly
Status:ok
Tags:
Comment:
1.18wmf1: MFT r106907 - r108532
Modified paths:
  • /branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.body.php (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.i18n.php (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.php (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccessTemplate.php (added) (history)
  • /branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/tests (added) (history)

Diff [purge]

Index: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.php
@@ -0,0 +1,46 @@
 2+<?php
 3+/**
 4+ * Extension ZeroRatedMobileAccess — Zero Rated Mobile Access
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ * @author Patrick Reilly
 9+ * @copyright © 2011 Patrick Reilly
 10+ * @licence GNU General Public Licence 2.0 or later
 11+ */
 12+
 13+// Needs to be called within MediaWiki; not standalone
 14+if ( !defined( 'MEDIAWIKI' ) ) {
 15+ echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" );
 16+ die( -1 );
 17+}
 18+
 19+// Extension credits that will show up on Special:Version
 20+$wgExtensionCredits['other'][] = array(
 21+ 'path' => __FILE__,
 22+ 'name' => 'ZeroRatedMobileAccess',
 23+ 'version' => '0.0.1',
 24+ 'author' => array( 'Patrick Reilly' ),
 25+ 'descriptionmsg' => 'zero-rated-mobile-access-desc',
 26+ 'url' => 'https://www.mediawiki.org/wiki/Extension:ZeroRatedMobileAccess',
 27+);
 28+
 29+$cwd = dirname( __FILE__ ) . DIRECTORY_SEPARATOR;
 30+$wgExtensionMessagesFiles['ZeroRatedMobileAccess'] = $cwd . 'ZeroRatedMobileAccess.i18n.php';
 31+
 32+// autoload extension classes
 33+
 34+$autoloadClasses = array (
 35+ 'ZeroRatedMobileAccessTemplate' => 'ZeroRatedMobileAccessTemplate',
 36+ 'ExtZeroRatedMobileAccess' => 'ZeroRatedMobileAccess.body',
 37+);
 38+
 39+foreach ( $autoloadClasses as $className => $classFilename ) {
 40+ $wgAutoloadClasses[$className] = $cwd . $classFilename . '.php';
 41+}
 42+
 43+$wgEnableZeroRatedMobileAccessTesting = false;
 44+
 45+$wgExtZeroRatedMobileAccess = new ExtZeroRatedMobileAccess();
 46+
 47+$wgHooks['BeforePageDisplay'][] = array( &$wgExtZeroRatedMobileAccess, 'beforePageDisplayHTML' );
\ No newline at end of file
Property changes on: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.php
___________________________________________________________________
Added: svn:eol-style
148 + native
Index: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.body.php
@@ -0,0 +1,811 @@
 2+<?php
 3+
 4+class ExtZeroRatedMobileAccess {
 5+ const VERSION = '0.0.7';
 6+
 7+ public static $renderZeroRatedLandingPage;
 8+ public static $renderZeroRatedBanner;
 9+ private static $debugOutput = array();
 10+ private static $displayDebugOutput = false;
 11+ private static $formatMobileUrl = '//%s.m.wikipedia.org/';
 12+ private static $title;
 13+ private static $isFilePage;
 14+ private static $acceptBilling;
 15+ private static $carrier;
 16+ private static $renderZeroRatedRedirect;
 17+ private static $forceClickToViewImages;
 18+ public static $useFormat;
 19+
 20+ /**
 21+ * Handler for the BeforePageDisplay hook
 22+ *
 23+ * @param $out OutputPage
 24+ * @param $text String
 25+ * @return bool
 26+ */
 27+ public function beforePageDisplayHTML( &$out, &$text ) {
 28+ global $wgRequest, $wgConf, $wgDBname, $wgEnableZeroRatedMobileAccessTesting;
 29+ wfProfileIn( __METHOD__ );
 30+
 31+ list( $site, $lang ) = $wgConf->siteFromDB( $wgDBname );
 32+ if ( $site == 'wikipedia' || $wgEnableZeroRatedMobileAccessTesting ) {
 33+
 34+ $xDevice = isset( $_SERVER['HTTP_X_DEVICE'] ) ? $_SERVER['HTTP_X_DEVICE'] : '';
 35+ self::$useFormat = $wgRequest->getText( 'useformat' );
 36+
 37+ if ( self::$useFormat !== 'mobile' && self::$useFormat !== 'mobile-wap' &&
 38+ !$xDevice ) {
 39+ wfProfileOut( __METHOD__ );
 40+ return true;
 41+ }
 42+
 43+ $output = Html::openElement( 'div',
 44+ array( 'id' => 'zero-landing-page' ) );
 45+
 46+ self::$renderZeroRatedLandingPage = $wgRequest->getFuzzyBool( 'renderZeroRatedLandingPage' );
 47+ self::$renderZeroRatedBanner = $wgRequest->getFuzzyBool( 'renderZeroRatedBanner' );
 48+ self::$renderZeroRatedRedirect = $wgRequest->getFuzzyBool( 'renderZeroRatedRedirect' );
 49+ self::$forceClickToViewImages = $wgRequest->getFuzzyBool( 'forceClickToViewImages' );
 50+ self::$acceptBilling = $wgRequest->getVal( 'acceptbilling' );
 51+ self::$title = $out->getTitle();
 52+
 53+ $carrier = $wgRequest->getHeader( 'HTTP_X_CARRIER' );
 54+ if ( $carrier !== '(null)' && $carrier ) {
 55+ self::$renderZeroRatedBanner = true;
 56+ }
 57+
 58+ if ( self::$title->getNamespace() == NS_FILE ) {
 59+ self::$isFilePage = true;
 60+ }
 61+
 62+ if ( self::$acceptBilling === 'no' ) {
 63+ $targetUrl = $wgRequest->getVal( 'returnto' );
 64+ $out->redirect( $targetUrl, '301' );
 65+ $out->output();
 66+ }
 67+
 68+ if ( self::$acceptBilling === 'yes' ) {
 69+ $targetUrl = $wgRequest->getVal( 'returnto' );
 70+ if ( $targetUrl ) {
 71+ $out->redirect( $targetUrl, '301' );
 72+ $out->output();
 73+ }
 74+ }
 75+
 76+ if ( self::$isFilePage && self::$acceptBilling !== 'yes' ) {
 77+ $acceptBillingYes = Html::rawElement( 'a',
 78+ array('href' => $wgRequest->appendQuery( 'renderZeroRatedBanner=true&acceptbilling=yes' ) ),
 79+ wfMsg( 'zero-rated-mobile-access-banner-text-data-charges-yes' ) );
 80+ $referrer = $wgRequest->getHeader( 'referer' );
 81+ $acceptBillingNo = Html::rawElement( 'a',
 82+ array('href' => $wgRequest->appendQuery( 'acceptbilling=no&returnto=' . urlencode( $referrer ) ) ),
 83+ wfMsg( 'zero-rated-mobile-access-banner-text-data-charges-no' ) );
 84+ $bannerText = Html::rawElement( 'h3',
 85+ array( 'id' => 'zero-rated-banner-text' ),
 86+ wfMsg( 'zero-rated-mobile-access-banner-text-data-charges', $acceptBillingYes, $acceptBillingNo ) );
 87+ $banner = Html::rawElement( 'div',
 88+ array( 'style' => 'display:none;',
 89+ 'id' => 'zero-rated-banner-red' ),
 90+ $bannerText
 91+ );
 92+ $output .= $banner;
 93+ $out->clearHTML();
 94+ $out->setPageTitle( null );
 95+ } elseif ( self::$renderZeroRatedRedirect === true ) {
 96+ $returnto = $wgRequest->getVal( 'returnto' );
 97+ $acceptBillingYes = Html::rawElement( 'a',
 98+ array('href' => $wgRequest->appendQuery( 'renderZeroRatedBanner=true&acceptbilling=yes&returnto=' . urlencode( $returnto ) ) ),
 99+ wfMsg( 'zero-rated-mobile-access-banner-text-data-charges-yes' ) );
 100+ $referrer = $wgRequest->getHeader( 'referer' );
 101+ $acceptBillingNo = Html::rawElement( 'a',
 102+ array('href' => $wgRequest->appendQuery( 'acceptbilling=no&returnto=' . urlencode( $referrer ) ) ),
 103+ wfMsg( 'zero-rated-mobile-access-banner-text-data-charges-no' ) );
 104+ $bannerText = Html::rawElement( 'h3',
 105+ array( 'id' => 'zero-rated-banner-text' ),
 106+ wfMsg( 'zero-rated-mobile-access-banner-text-data-charges', $acceptBillingYes, $acceptBillingNo ) );
 107+ $banner = Html::rawElement( 'div',
 108+ array( 'style' => 'display:none;',
 109+ 'id' => 'zero-rated-banner-red' ),
 110+ $bannerText
 111+ );
 112+ $output .= $banner;
 113+ $out->clearHTML();
 114+ $out->setPageTitle( null );
 115+ } elseif ( self::$renderZeroRatedBanner === true ) {
 116+ // a2enmod headers >>> .htaccess >>> RequestHeader set HTTP_CARRIER Verizon
 117+ self::$carrier = $this->lookupCarrier( $carrier );
 118+ $html = $out->getHTML();
 119+ $parsedHtml = $this->parseLinksForZeroQueryString( $html );
 120+ $out->clearHTML();
 121+ $out->addHTML( $parsedHtml );
 122+ $carrierLink = ( isset( self::$carrier['link'] ) ) ? self::$carrier['link'] : '';
 123+ $bannerText = Html::rawElement( 'h3',
 124+ array( 'id' => 'zero-rated-banner-text' ),
 125+ wfMsg( 'zero-rated-mobile-access-banner-text', $carrierLink ) );
 126+ $banner = Html::rawElement( 'div',
 127+ array( 'style' => 'display:none;',
 128+ 'id' => 'zero-rated-banner' ),
 129+ $bannerText
 130+ );
 131+ $output .= $banner;
 132+ }
 133+ if ( self::$renderZeroRatedLandingPage === true ) {
 134+ $out->clearHTML();
 135+ $out->setPageTitle( null );
 136+ $output .= wfMsg( 'zero-rated-mobile-access-desc' );
 137+ $languageNames = Language::getLanguageNames();
 138+ $country = $wgRequest->getVal( 'country' );
 139+ $ip = $wgRequest->getVal( 'ip', wfGetIP() );
 140+ // Temporary hack to allow for testing on localhost
 141+ $countryIps = array(
 142+ 'GERMANY' => '80.237.226.75',
 143+ 'MEXICO' => '187.184.240.247',
 144+ 'THAILAND' => '180.180.150.104',
 145+ 'FRANCE' => '90.6.70.28',
 146+ );
 147+ $ip = ( strpos( $ip, '192.168.' ) === 0 ) ? $countryIps['THAILAND'] : $ip;
 148+ if ( IP::isValid( $ip ) ) {
 149+ // If no country was passed, try to do GeoIP lookup
 150+ // Requires php5-geoip package
 151+ if ( !$country && function_exists( 'geoip_country_code_by_name' ) ) {
 152+ $country = geoip_country_code_by_name( $ip );
 153+ }
 154+ self::addDebugOutput( $country );
 155+ }
 156+ $languageOptions = self::createLanguageOptionsFromWikiText();
 157+ //self::$displayDebugOutput = true;
 158+ $languagesForCountry = ( isset( $languageOptions[self::getFullCountryNameFromCode( $country )] ) ) ?
 159+ $languageOptions[self::getFullCountryNameFromCode( $country )] : null;
 160+ //self::addDebugOutput( $languageOptions );
 161+ self::addDebugOutput( self::getFullCountryNameFromCode( $country ) );
 162+ self::addDebugOutput( $languagesForCountry );
 163+ self::writeDebugOutput();
 164+
 165+ if ( is_array( $languagesForCountry ) ) {
 166+ $sizeOfLanguagesForCountry = sizeof( $languagesForCountry );
 167+ for ( $i = 0; $i < $sizeOfLanguagesForCountry; $i++ ) {
 168+ $languageName = $languageNames[$languagesForCountry[$i]['language']];
 169+ $languageCode = $languagesForCountry[$i]['language'];
 170+ $output .= Html::element( 'hr' );
 171+ $output .= Html::element( 'h3',
 172+ array( 'id' => 'lang_' . $languageCode ),
 173+ $languageName
 174+ );
 175+ if ( $i == 0 ) {
 176+ $output .= self::getSearchFormHtml( $languageCode );
 177+ } else {
 178+ $languageUrl = sprintf( self::$formatMobileUrl, $languageCode );
 179+ $output .= Html::element( 'a',
 180+ array( 'id' => 'lang_' . $languageCode,
 181+ 'href' => $languageUrl ),
 182+ wfMessage( 'zero-rated-mobile-access-home-page-selection',
 183+ $languageName )->inLanguage( $languageCode )
 184+ );
 185+ $output .= Html::element( 'br' );
 186+ }
 187+ }
 188+ }
 189+ $output .= Html::element( 'hr' );
 190+ $output .= wfMsg( 'zero-rated-mobile-access-home-page-selection-text' );
 191+ $output .= Html::openElement( 'select',
 192+ array( 'id' => 'languageselection',
 193+ 'onchange' => 'javascript:window.location = this.options[this.selectedIndex].value;',
 194+ )
 195+ );
 196+ $output .= Html::element( 'option',
 197+ array( 'value' => '' ),
 198+ wfMsg( 'zero-rated-mobile-access-language-selection' )
 199+ );
 200+ foreach ( $languageNames as $languageCode => $languageName ) {
 201+ $output .= Html::element( 'option',
 202+ array( 'value' => sprintf( self::$formatMobileUrl, $languageCode ) ),
 203+ $languageName
 204+ );
 205+ }
 206+ $output .= Html::closeElement( 'select' );
 207+ }
 208+
 209+ $output .= Html::closeElement( 'div' );
 210+ if ( $output != '<div id="zero-landing-page"></div>' ) {
 211+ $out->addHTML( $output );
 212+ }
 213+ }
 214+ wfProfileOut( __METHOD__ );
 215+ return true;
 216+ }
 217+
 218+ /**
 219+ * Returns information about carrier
 220+ *
 221+ * @param String $carrier: Name of carrier e.g., "Verizon Wireless"
 222+ * @return Array
 223+ */
 224+ private function lookupCarrier( $carrier ) {
 225+ wfProfileIn( __METHOD__ );
 226+ $carrierLinkData = array();
 227+ $carrier = strtoupper( $carrier );
 228+
 229+ $allCarrierLinkData = $this->createCarrierOptionsFromWikiText();
 230+
 231+ if ( is_array( $allCarrierLinkData ) ) {
 232+ if ( isset( $allCarrierLinkData[$carrier] ) ) {
 233+ $carrierLinkData = $allCarrierLinkData[$carrier];
 234+ }
 235+ }
 236+
 237+ wfProfileOut( __METHOD__ );
 238+ return $carrierLinkData;
 239+ }
 240+
 241+ /**
 242+ * Returns the Html of a page with the various links appended with zeropartner parameter
 243+ *
 244+ * @param String $html: Html of current page
 245+ * @return String
 246+ */
 247+ private function parseLinksForZeroQueryString( $html ) {
 248+ wfProfileIn( __METHOD__ );
 249+ $html = mb_convert_encoding( $html, 'HTML-ENTITIES', "UTF-8" );
 250+ libxml_use_internal_errors( true );
 251+ $doc = new DOMDocument();
 252+ $doc->loadHTML( '<?xml encoding="UTF-8">' . $html );
 253+ libxml_use_internal_errors( false );
 254+ $doc->preserveWhiteSpace = false;
 255+ $doc->strictErrorChecking = false;
 256+ $doc->encoding = 'UTF-8';
 257+
 258+ $xpath = new DOMXpath( $doc );
 259+
 260+ if ( !self::$isFilePage && self::$forceClickToViewImages ) {
 261+ $tagToReplace = 'img';
 262+ $tagToReplaceNodes = $doc->getElementsByTagName( $tagToReplace );
 263+ foreach ( $tagToReplaceNodes as $tagToReplaceNode ) {
 264+ if ( $tagToReplaceNode ) {
 265+ $alt = $tagToReplaceNode->getAttribute( 'alt' );
 266+ $spanNodeText = wfMsg( 'zero-rated-mobile-access-click-to-view-image', lcfirst( substr( $alt, 0, 40 ) ) );
 267+ $spanNode = $doc->createElement( "span", str_replace( "&", "&amp;", $spanNodeText ) );
 268+ if ( $alt ) {
 269+ $spanNode->setAttribute( 'title', $alt );
 270+ }
 271+ $tagToReplaceNode->parentNode->replaceChild( $spanNode, $tagToReplaceNode );
 272+ }
 273+ }
 274+ }
 275+
 276+ $zeroRatedLinks = $xpath->query( "//a[not(contains(@class,'external'))]" );
 277+ foreach ( $zeroRatedLinks as $zeroRatedLink ) {
 278+ $zeroRatedLinkHref = $zeroRatedLink->getAttribute( 'href' );
 279+ if ( $zeroRatedLinkHref && substr( $zeroRatedLinkHref, 0, 1 ) !== '#' ) {
 280+ $zeroPartnerUrl = $this->appendQueryString( $zeroRatedLinkHref,
 281+ array( array( 'name' => 'zeropartner',
 282+ 'value' => ( isset( self::$carrier['partnerId'] ) ) ? self::$carrier['partnerId'] : 0 ),
 283+ array('name' => 'renderZeroRatedBanner',
 284+ 'value' => 'true') ) );
 285+ if ( $zeroPartnerUrl ) {
 286+ $zeroRatedLink->setAttribute( 'href', $zeroPartnerUrl );
 287+ }
 288+ }
 289+ }
 290+
 291+ $zeroRatedExternalLinks = $xpath->query( "//a[contains(@class,'external')]" );
 292+ foreach ( $zeroRatedExternalLinks as $zeroRatedExternalLink ) {
 293+ $zeroRatedExternalLinkHref = $zeroRatedExternalLink->getAttribute( 'href' );
 294+ if ( $zeroRatedExternalLinkHref && substr( $zeroRatedExternalLinkHref, 0, 1 ) !== '#' ) {
 295+ $zeroPartnerUrl = $this->appendQueryString( $zeroRatedLinkHref,
 296+ array( array( 'name' => 'zeropartner',
 297+ 'value' => ( isset( self::$carrier['partnerId'] ) ) ? self::$carrier['partnerId'] : 0 ),
 298+ array('name' => 'renderZeroRatedBanner',
 299+ 'value' => 'true') ) );
 300+ if ( $zeroPartnerUrl ) {
 301+ $zeroRatedExternalLink->setAttribute( 'href', '?renderZeroRatedRedirect=true&returnto=' . urlencode($zeroRatedExternalLinkHref) );
 302+ }
 303+ }
 304+ }
 305+
 306+ $output = $doc->saveXML( null, LIBXML_NOEMPTYTAG );
 307+ wfProfileOut( __METHOD__ );
 308+ return $output;
 309+ }
 310+
 311+ /**
 312+ * Returns the url with querystring parameters appended
 313+ *
 314+ * @param String $url: valid url to append querystring
 315+ * @param Array $queryStringParameters: array of parameters to add to querystring
 316+ * @return String
 317+ */
 318+ private function appendQueryString( $url, $queryStringParameters ) {
 319+ wfProfileIn( __METHOD__ );
 320+ $parsedUrl = parse_url( $url );
 321+ if ( isset( $parsedUrl['query'] ) ) {
 322+ parse_str( $parsedUrl['query'], $queryString );
 323+ foreach ( $queryStringParameters as $queryStringParameter ) {
 324+ $queryString[$queryStringParameter['name']] = $queryStringParameter['value'];
 325+ }
 326+ $parsedUrl['query'] = http_build_query( $queryString );
 327+ } else {
 328+ $parsedUrl['query'] = '';
 329+ foreach ( $queryStringParameters as $queryStringParameter ) {
 330+ $parsedUrl['query'] .= "{$queryStringParameter['name']}={$queryStringParameter['value']}&";
 331+ }
 332+ if ( substr( $parsedUrl['query'], -1, 1 ) === '&' ) {
 333+ $parsedUrl['query'] = substr( $parsedUrl['query'], 0, -1 );
 334+ }
 335+ }
 336+ wfProfileOut( __METHOD__ );
 337+ return $this->unParseUrl( $parsedUrl );
 338+ }
 339+
 340+ /**
 341+ * Returns the full url
 342+ *
 343+ * @param Array $parsedUrl: the array returned from parse_url
 344+ * @return String
 345+ */
 346+ private function unParseUrl( $parsedUrl ) {
 347+ wfProfileIn( __METHOD__ );
 348+ $scheme = isset( $parsedUrl['scheme'] ) ? $parsedUrl['scheme'] . '://' : '';
 349+ $host = isset( $parsedUrl['host'] ) ? $parsedUrl['host'] : '';
 350+ $port = isset( $parsedUrl['port'] ) ? ':' . $parsedUrl['port'] : '';
 351+ $user = isset( $parsedUrl['user'] ) ? $parsedUrl['user'] : '';
 352+ $pass = isset( $parsedUrl['pass'] ) ? ':' . $parsedUrl['pass'] : '';
 353+ $pass = ( $user || $pass ) ? "$pass@" : '';
 354+ $path = isset( $parsedUrl['path'] ) ? $parsedUrl['path'] : '';
 355+ $query = isset( $parsedUrl['query'] ) ? '?' . $parsedUrl['query'] : '';
 356+ $fragment = isset( $parsedUrl['fragment'] ) ? '#' . $parsedUrl['fragment'] : '';
 357+ wfProfileOut( __METHOD__ );
 358+ return "$scheme$user$pass$host$port$path$query$fragment";
 359+ }
 360+
 361+ /**
 362+ * Adds object to debugOutput Array
 363+ *
 364+ * @param Object $object: any valid PHP object
 365+ * @return bool
 366+ */
 367+ private static function addDebugOutput( $object ) {
 368+ wfProfileIn( __METHOD__ );
 369+ if ( is_array( self::$debugOutput ) ) {
 370+ self::$debugOutput[] = $object;
 371+ }
 372+ wfProfileOut( __METHOD__ );
 373+ return true;
 374+ }
 375+
 376+ /**
 377+ * Writes objects from the debugOutput Array to buffer
 378+ *
 379+ * @return bool
 380+ */
 381+ private static function writeDebugOutput() {
 382+ wfProfileIn( __METHOD__ );
 383+ if ( self::$debugOutput && self::$displayDebugOutput === true ) {
 384+ echo "<pre>";
 385+ foreach( self::$debugOutput as $debugOutput ) {
 386+ var_dump( $debugOutput );
 387+ }
 388+ echo "</pre>";
 389+ }
 390+ wfProfileOut( __METHOD__ );
 391+ return true;
 392+ }
 393+
 394+ private static function createCarrierOptionsFromWikiText() {
 395+ global $wgMemc;
 396+ wfProfileIn( __METHOD__ );
 397+ $carrierOptionsWikiPage = wfMsg( 'zero-rated-mobile-access-carrier-options-wiki-page' );
 398+ $title = Title::newFromText( $carrierOptionsWikiPage, NS_MEDIAWIKI );
 399+ // Use the revision directly to prevent other hooks to be called
 400+ $rev = Revision::newFromTitle( $title );
 401+ if ( $rev ) {
 402+ $sha1OfRev = $rev->getSha1();
 403+ $key = wfMemcKey( 'zero-rated-mobile-access-carrier-options', $sha1OfRev );
 404+ $carrierOptions = $wgMemc->get( $key );
 405+ } else {
 406+ $carrierOptions = null;
 407+ }
 408+
 409+ if ( !$carrierOptions ) {
 410+ $carrierOptions = array();
 411+ $lines = array();
 412+ if ( $rev ) {
 413+ $lines = explode( "\n", $rev->getRawText() );
 414+ }
 415+ if ( $lines && count( $lines ) > 0 ) {
 416+ $sizeOfLines = sizeof( $lines );
 417+ for ( $i = 0; $i < $sizeOfLines; $i++ ) {
 418+ $line = $lines[$i];
 419+ if ( strpos( $line, '*' ) === 0 && strpos( $line, '**' ) !== 0 && $i >= 0 ) {
 420+ $carrierName = strtoupper( str_replace( '* ', '', $line ) );
 421+ $carrierRaw = str_replace( '* ', '', $line );
 422+ $carrierOptions[$carrierName] = '';
 423+ $carrierOptions[$carrierName]['name'] = $carrierRaw;
 424+ } elseif ( strpos( $line, '**' ) === 0 && $i > 0 ) {
 425+ if ( $i % 3 === 1 ) {
 426+ $carrierOptions[$carrierName]['url'] = trim( str_replace( '** ', '', $line ) );
 427+ $carrierLink = Html::rawElement( 'a',
 428+ array('href' => $carrierOptions[$carrierName]['url'] ),
 429+ $carrierOptions[$carrierName]['name'] );
 430+ $carrierOptions[$carrierName]['link'] = $carrierLink;
 431+ } elseif ( $i % 3 === 2 ) {
 432+ $carrierOptions[$carrierName]['partnerId'] = intval( trim( str_replace( '** ', '', $line ) ) );
 433+ }
 434+ }
 435+ }
 436+ }
 437+ $wgMemc->set( $key, $carrierOptions, self::getMaxAge() );
 438+ }
 439+ wfProfileOut( __METHOD__ );
 440+ return $carrierOptions;
 441+ }
 442+
 443+ /**
 444+ * Returns the language options array parsed from a valid Wiki page
 445+ *
 446+ * @return Array
 447+ */
 448+ private static function createLanguageOptionsFromWikiText() {
 449+ global $wgMemc;
 450+ wfProfileIn( __METHOD__ );
 451+ $languageOptionsWikiPage = wfMsgForContent( 'zero-rated-mobile-access-language-options-wiki-page' );
 452+ $title = Title::newFromText( $languageOptionsWikiPage, NS_MEDIAWIKI );
 453+ // Use the revision directly to prevent other hooks to be called
 454+ $rev = Revision::newFromTitle( $title );
 455+ if ( $rev ) {
 456+ $sha1OfRev = $rev->getSha1();
 457+ $key = wfMemcKey( 'zero-rated-mobile-access-language-options', $sha1OfRev );
 458+ $languageOptions = $wgMemc->get( $key );
 459+ } else {
 460+ $languageOptions = null;
 461+ }
 462+
 463+ if ( !$languageOptions ) {
 464+ $languageOptions = array();
 465+ $lines = array();
 466+ if ( $rev ) {
 467+ $lines = explode( "\n", $rev->getRawText() );
 468+ }
 469+ if ( $lines && count( $lines ) > 0 ) {
 470+ $sizeOfLines = sizeof( $lines );
 471+ for ( $i = 0; $i < $sizeOfLines; $i++ ) {
 472+ $line = $lines[$i];
 473+ if ( strpos( $line, '*' ) === 0 && strpos( $line, '**' ) !== 0 && $i >= 0 ) {
 474+ $countryName = strtoupper( str_replace( '* ', '', $line ) );
 475+ $languageOptions[$countryName] = '';
 476+ } elseif ( strpos( $line, '**' ) === 0 && $i > 0 ) {
 477+ $lineParts = explode('#', $line);
 478+ $language = ( isset( $lineParts[0] ) ) ?
 479+ trim( str_replace( '** ', '', $lineParts[0] ) ) :
 480+ trim( str_replace( '** ', '', $line ) ) ;
 481+ if ( $language !== 'portal' && $language !== 'other' ) {
 482+ $languageOptions[$countryName][] = ( isset( $lineParts[1] ) ) ?
 483+ array( 'language' => $language,
 484+ 'percentage' => intval( str_replace( '%', '', trim( $lineParts[1] ) ) ) ) :
 485+ $language;
 486+ }
 487+ }
 488+ }
 489+ }
 490+ $wgMemc->set( $key, $languageOptions, self::getMaxAge() );
 491+ }
 492+ wfProfileOut( __METHOD__ );
 493+ return $languageOptions;
 494+ }
 495+
 496+ /**
 497+ * Returns the Unix timestamp of current day's first second
 498+ *
 499+ * @return int: Timestamp
 500+ */
 501+ private static function todaysStart() {
 502+ wfProfileIn( __METHOD__ );
 503+ static $time = false;
 504+ if ( !$time ) {
 505+ global $wgLocaltimezone;
 506+ if ( isset( $wgLocaltimezone ) ) {
 507+ $tz = new DateTimeZone( $wgLocaltimezone );
 508+ } else {
 509+ $tz = new DateTimeZone( date_default_timezone_get() );
 510+ }
 511+ $dt = new DateTime( 'now', $tz );
 512+ $dt->setTime( 0, 0, 0 );
 513+ $time = $dt->getTimestamp();
 514+ }
 515+ wfProfileOut( __METHOD__ );
 516+ return $time;
 517+ }
 518+
 519+ /**
 520+ * Returns the number of seconds an item should stay in cache
 521+ *
 522+ * @return int: Time in seconds
 523+ */
 524+ private static function getMaxAge() {
 525+ wfProfileIn( __METHOD__ );
 526+ // add 10 seconds to cater for the time deviation between servers
 527+ $expiry = self::todaysStart() + 24 * 3600 - wfTimestamp() + 10;
 528+ wfProfileOut( __METHOD__ );
 529+ return min( $expiry, 3600 );
 530+ }
 531+
 532+ /**
 533+ * Get full country name from code
 534+ *
 535+ * @param string $code: alpha-2 code ISO 3166 country code
 536+ * @return String
 537+ */
 538+ private static function getFullCountryNameFromCode( $code ) {
 539+ wfProfileIn( __METHOD__ );
 540+ $countries = array(
 541+ 'AF' => 'AFGHANISTAN',
 542+ 'AL' => 'ALBANIA',
 543+ 'DZ' => 'ALGERIA',
 544+ 'AS' => 'AMERICAN SAMOA',
 545+ 'AD' => 'ANDORRA',
 546+ 'AO' => 'ANGOLA',
 547+ 'AI' => 'ANGUILLA',
 548+ 'AQ' => 'ANTARCTICA',
 549+ 'AG' => 'ANTIGUA AND BARBUDA',
 550+ 'AR' => 'ARGENTINA',
 551+ 'AM' => 'ARMENIA',
 552+ 'AW' => 'ARUBA',
 553+ 'AU' => 'AUSTRALIA',
 554+ 'AT' => 'AUSTRIA',
 555+ 'AZ' => 'AZERBAIJAN',
 556+ 'BS' => 'BAHAMAS',
 557+ 'BH' => 'BAHRAIN',
 558+ 'BD' => 'BANGLADESH',
 559+ 'BB' => 'BARBADOS',
 560+ 'BY' => 'BELARUS',
 561+ 'BE' => 'BELGIUM',
 562+ 'BZ' => 'BELIZE',
 563+ 'BJ' => 'BENIN',
 564+ 'BM' => 'BERMUDA',
 565+ 'BT' => 'BHUTAN',
 566+ 'BO' => 'BOLIVIA',
 567+ 'BA' => 'BOSNIA AND HERZEGOVINA',
 568+ 'BW' => 'BOTSWANA',
 569+ 'BV' => 'BOUVET ISLAND',
 570+ 'BR' => 'BRAZIL',
 571+ 'IO' => 'BRITISH INDIAN OCEAN TERRITORY',
 572+ 'BN' => 'BRUNEI DARUSSALAM',
 573+ 'BG' => 'BULGARIA',
 574+ 'BF' => 'BURKINA FASO',
 575+ 'BI' => 'BURUNDI',
 576+ 'KH' => 'CAMBODIA',
 577+ 'CM' => 'CAMEROON',
 578+ 'CA' => 'CANADA',
 579+ 'CV' => 'CAPE VERDE',
 580+ 'KY' => 'CAYMAN ISLANDS',
 581+ 'CF' => 'CENTRAL AFRICAN REPUBLIC',
 582+ 'TD' => 'CHAD',
 583+ 'CL' => 'CHILE',
 584+ 'CN' => 'CHINA',
 585+ 'CX' => 'CHRISTMAS ISLAND',
 586+ 'CC' => 'COCOS (KEELING) ISLANDS',
 587+ 'CO' => 'COLOMBIA',
 588+ 'KM' => 'COMOROS',
 589+ 'CG' => 'CONGO',
 590+ 'CD' => 'CONGO, THE DEMOCRATIC REPUBLIC OF THE',
 591+ 'CK' => 'COOK ISLANDS',
 592+ 'CR' => 'COSTA RICA',
 593+ 'CI' => 'COTE D IVOIRE',
 594+ 'HR' => 'CROATIA',
 595+ 'CU' => 'CUBA',
 596+ 'CY' => 'CYPRUS',
 597+ 'CZ' => 'CZECH REPUBLIC',
 598+ 'DK' => 'DENMARK',
 599+ 'DJ' => 'DJIBOUTI',
 600+ 'DM' => 'DOMINICA',
 601+ 'DO' => 'DOMINICAN REPUBLIC',
 602+ 'TP' => 'EAST TIMOR',
 603+ 'EC' => 'ECUADOR',
 604+ 'EG' => 'EGYPT',
 605+ 'SV' => 'EL SALVADOR',
 606+ 'GQ' => 'EQUATORIAL GUINEA',
 607+ 'ER' => 'ERITREA',
 608+ 'EE' => 'ESTONIA',
 609+ 'ET' => 'ETHIOPIA',
 610+ 'FK' => 'FALKLAND ISLANDS (MALVINAS)',
 611+ 'FO' => 'FAROE ISLANDS',
 612+ 'FJ' => 'FIJI',
 613+ 'FI' => 'FINLAND',
 614+ 'FR' => 'FRANCE',
 615+ 'GF' => 'FRENCH GUIANA',
 616+ 'PF' => 'FRENCH POLYNESIA',
 617+ 'TF' => 'FRENCH SOUTHERN TERRITORIES',
 618+ 'GA' => 'GABON',
 619+ 'GM' => 'GAMBIA',
 620+ 'GE' => 'GEORGIA',
 621+ 'DE' => 'GERMANY',
 622+ 'GH' => 'GHANA',
 623+ 'GI' => 'GIBRALTAR',
 624+ 'GR' => 'GREECE',
 625+ 'GL' => 'GREENLAND',
 626+ 'GD' => 'GRENADA',
 627+ 'GP' => 'GUADELOUPE',
 628+ 'GU' => 'GUAM',
 629+ 'GT' => 'GUATEMALA',
 630+ 'GN' => 'GUINEA',
 631+ 'GW' => 'GUINEA-BISSAU',
 632+ 'GY' => 'GUYANA',
 633+ 'HT' => 'HAITI',
 634+ 'HM' => 'HEARD ISLAND AND MCDONALD ISLANDS',
 635+ 'VA' => 'HOLY SEE (VATICAN CITY STATE)',
 636+ 'HN' => 'HONDURAS',
 637+ 'HK' => 'HONG KONG',
 638+ 'HU' => 'HUNGARY',
 639+ 'IS' => 'ICELAND',
 640+ 'IN' => 'INDIA',
 641+ 'ID' => 'INDONESIA',
 642+ 'IR' => 'IRAN, ISLAMIC REPUBLIC OF',
 643+ 'IQ' => 'IRAQ',
 644+ 'IE' => 'IRELAND',
 645+ 'IL' => 'ISRAEL',
 646+ 'IT' => 'ITALY',
 647+ 'JM' => 'JAMAICA',
 648+ 'JP' => 'JAPAN',
 649+ 'JO' => 'JORDAN',
 650+ 'KZ' => 'KAZAKSTAN',
 651+ 'KE' => 'KENYA',
 652+ 'KI' => 'KIRIBATI',
 653+ 'KP' => 'KOREA DEMOCRATIC PEOPLES REPUBLIC OF',
 654+ 'KR' => 'KOREA REPUBLIC OF',
 655+ 'KW' => 'KUWAIT',
 656+ 'KG' => 'KYRGYZSTAN',
 657+ 'LA' => 'LAO PEOPLES DEMOCRATIC REPUBLIC',
 658+ 'LV' => 'LATVIA',
 659+ 'LB' => 'LEBANON',
 660+ 'LS' => 'LESOTHO',
 661+ 'LR' => 'LIBERIA',
 662+ 'LY' => 'LIBYAN ARAB JAMAHIRIYA',
 663+ 'LI' => 'LIECHTENSTEIN',
 664+ 'LT' => 'LITHUANIA',
 665+ 'LU' => 'LUXEMBOURG',
 666+ 'MO' => 'MACAU',
 667+ 'MK' => 'MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF',
 668+ 'MG' => 'MADAGASCAR',
 669+ 'MW' => 'MALAWI',
 670+ 'MY' => 'MALAYSIA',
 671+ 'MV' => 'MALDIVES',
 672+ 'ML' => 'MALI',
 673+ 'MT' => 'MALTA',
 674+ 'MH' => 'MARSHALL ISLANDS',
 675+ 'MQ' => 'MARTINIQUE',
 676+ 'MR' => 'MAURITANIA',
 677+ 'MU' => 'MAURITIUS',
 678+ 'YT' => 'MAYOTTE',
 679+ 'MX' => 'MEXICO',
 680+ 'FM' => 'MICRONESIA, FEDERATED STATES OF',
 681+ 'MD' => 'MOLDOVA, REPUBLIC OF',
 682+ 'MC' => 'MONACO',
 683+ 'MN' => 'MONGOLIA',
 684+ 'MS' => 'MONTSERRAT',
 685+ 'MA' => 'MOROCCO',
 686+ 'MZ' => 'MOZAMBIQUE',
 687+ 'MM' => 'MYANMAR',
 688+ 'NA' => 'NAMIBIA',
 689+ 'NR' => 'NAURU',
 690+ 'NP' => 'NEPAL',
 691+ 'NL' => 'NETHERLANDS',
 692+ 'AN' => 'NETHERLANDS ANTILLES',
 693+ 'NC' => 'NEW CALEDONIA',
 694+ 'NZ' => 'NEW ZEALAND',
 695+ 'NI' => 'NICARAGUA',
 696+ 'NE' => 'NIGER',
 697+ 'NG' => 'NIGERIA',
 698+ 'NU' => 'NIUE',
 699+ 'NF' => 'NORFOLK ISLAND',
 700+ 'MP' => 'NORTHERN MARIANA ISLANDS',
 701+ 'NO' => 'NORWAY',
 702+ 'OM' => 'OMAN',
 703+ 'PK' => 'PAKISTAN',
 704+ 'PW' => 'PALAU',
 705+ 'PS' => 'PALESTINIAN TERRITORY, OCCUPIED',
 706+ 'PA' => 'PANAMA',
 707+ 'PG' => 'PAPUA NEW GUINEA',
 708+ 'PY' => 'PARAGUAY',
 709+ 'PE' => 'PERU',
 710+ 'PH' => 'PHILIPPINES',
 711+ 'PN' => 'PITCAIRN',
 712+ 'PL' => 'POLAND',
 713+ 'PT' => 'PORTUGAL',
 714+ 'PR' => 'PUERTO RICO',
 715+ 'QA' => 'QATAR',
 716+ 'RE' => 'REUNION',
 717+ 'RO' => 'ROMANIA',
 718+ 'RU' => 'RUSSIAN FEDERATION',
 719+ 'RW' => 'RWANDA',
 720+ 'SH' => 'SAINT HELENA',
 721+ 'KN' => 'SAINT KITTS AND NEVIS',
 722+ 'LC' => 'SAINT LUCIA',
 723+ 'PM' => 'SAINT PIERRE AND MIQUELON',
 724+ 'VC' => 'SAINT VINCENT AND THE GRENADINES',
 725+ 'WS' => 'SAMOA',
 726+ 'SM' => 'SAN MARINO',
 727+ 'ST' => 'SAO TOME AND PRINCIPE',
 728+ 'SA' => 'SAUDI ARABIA',
 729+ 'SN' => 'SENEGAL',
 730+ 'SC' => 'SEYCHELLES',
 731+ 'SL' => 'SIERRA LEONE',
 732+ 'SG' => 'SINGAPORE',
 733+ 'SK' => 'SLOVAKIA',
 734+ 'SI' => 'SLOVENIA',
 735+ 'SB' => 'SOLOMON ISLANDS',
 736+ 'SO' => 'SOMALIA',
 737+ 'ZA' => 'SOUTH AFRICA',
 738+ 'GS' => 'SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS',
 739+ 'ES' => 'SPAIN',
 740+ 'LK' => 'SRI LANKA',
 741+ 'SD' => 'SUDAN',
 742+ 'SR' => 'SURINAME',
 743+ 'SJ' => 'SVALBARD AND JAN MAYEN',
 744+ 'SZ' => 'SWAZILAND',
 745+ 'SE' => 'SWEDEN',
 746+ 'CH' => 'SWITZERLAND',
 747+ 'SY' => 'SYRIAN ARAB REPUBLIC',
 748+ 'TW' => 'TAIWAN, PROVINCE OF CHINA',
 749+ 'TJ' => 'TAJIKISTAN',
 750+ 'TZ' => 'TANZANIA, UNITED REPUBLIC OF',
 751+ 'TH' => 'THAILAND',
 752+ 'TG' => 'TOGO',
 753+ 'TK' => 'TOKELAU',
 754+ 'TO' => 'TONGA',
 755+ 'TT' => 'TRINIDAD AND TOBAGO',
 756+ 'TN' => 'TUNISIA',
 757+ 'TR' => 'TURKEY',
 758+ 'TM' => 'TURKMENISTAN',
 759+ 'TC' => 'TURKS AND CAICOS ISLANDS',
 760+ 'TV' => 'TUVALU',
 761+ 'UG' => 'UGANDA',
 762+ 'UA' => 'UKRAINE',
 763+ 'AE' => 'UNITED ARAB EMIRATES',
 764+ 'GB' => 'UNITED KINGDOM',
 765+ 'US' => 'UNITED STATES',
 766+ 'UM' => 'UNITED STATES MINOR OUTLYING ISLANDS',
 767+ 'UY' => 'URUGUAY',
 768+ 'UZ' => 'UZBEKISTAN',
 769+ 'VU' => 'VANUATU',
 770+ 'VE' => 'VENEZUELA',
 771+ 'VN' => 'VIET NAM',
 772+ 'VG' => 'VIRGIN ISLANDS, BRITISH',
 773+ 'VI' => 'VIRGIN ISLANDS, U.S.',
 774+ 'WF' => 'WALLIS AND FUTUNA',
 775+ 'EH' => 'WESTERN SAHARA',
 776+ 'YE' => 'YEMEN',
 777+ 'YU' => 'YUGOSLAVIA',
 778+ 'ZM' => 'ZAMBIA',
 779+ 'ZW' => 'ZIMBABWE',
 780+ );
 781+ wfProfileOut( __METHOD__ );
 782+ $code = ( strlen( $code ) === 2 ) ? strtoupper( $code ) : null;
 783+ return ( $code && isset( $countries[$code] ) ) ? $countries[$code] : null;
 784+ }
 785+
 786+ /**
 787+ * Search form for various languages
 788+ *
 789+ * @param string $langCode: alpha-2 code for language
 790+ * @return String
 791+ */
 792+ private static function getSearchFormHtml( $langCode ) {
 793+ wfProfileIn( __METHOD__ );
 794+ $searchValue = wfMessage( 'zero-rated-mobile-access-search' )->inLanguage( $langCode );
 795+ $formHtml = <<<HTML
 796+ <form id="zero-language-search" action="//{$langCode}.wikipedia.org/w/index.php" class="search_bar" method="get">
 797+ <input type="hidden" value="Special:Search" name="title">
 798+ <div id="sq" class="divclearable">
 799+ <input type="text" name="search" id="search" size="22" value="" autocorrect="off" autocomplete="off" autocapitalize="off" maxlength="1024">
 800+ <div class="clearlink" id="clearsearch" title="Clear"></div>
 801+ </div>
 802+ <button id="goButton" type="submit">{$searchValue}</button>
 803+ </form>
 804+HTML;
 805+ wfProfileOut( __METHOD__ );
 806+ return $formHtml;
 807+ }
 808+
 809+ public function getVersion() {
 810+ return __CLASS__ . ': $Id: ZeroRatedMobileAccess.body.php 108565 2012-01-10 23:42:04Z preilly $';
 811+ }
 812+}
Property changes on: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.body.php
___________________________________________________________________
Added: svn:eol-style
1813 + native
Index: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccessTemplate.php
@@ -0,0 +1,46 @@
 2+<?php
 3+
 4+abstract class ZeroRatedMobileAccessTemplate {
 5+ public $data;
 6+
 7+ /**
 8+ * Constructor
 9+ */
 10+ public function __construct() {
 11+ $this->data = array();
 12+ }
 13+
 14+ /**
 15+ * Sets the value $value to $name
 16+ * @param $name
 17+ * @param $value
 18+ */
 19+ public function set( $name, $value ) {
 20+ $this->data[$name] = $value;
 21+ }
 22+
 23+ /**
 24+ * Sets the value $value to $name
 25+ * @param $options array
 26+ */
 27+ public function setByArray( $options ) {
 28+ foreach ($options as $name => $value ) {
 29+ $this->set( $name, $value );
 30+ }
 31+ }
 32+
 33+ /**
 34+ * Gets the value of $name
 35+ * @param $name
 36+ * @return string
 37+ */
 38+ public function get( $name ) {
 39+ return $this->data[$name];
 40+ }
 41+
 42+ /**
 43+ * Main function, used by classes that subclass ZeroRatedMobileAccessTemplate
 44+ * to show the actual HTML output
 45+ */
 46+ abstract public function getHTML();
 47+}
Property changes on: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccessTemplate.php
___________________________________________________________________
Added: svn:eol-style
148 + native
Index: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.i18n.php
@@ -0,0 +1,58 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for the extension ZeroRatedMobileAccess
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ * @author Patrick Reilly
 9+ * @copyright © 2011 Patrick Reilly
 10+ * @licence GNU General Public Licence 2.0 or later
 11+ */
 12+
 13+$messages = array();
 14+
 15+/** English
 16+ * @author Patrick Reilly
 17+ */
 18+$messages['en'] = array (
 19+ 'zero-rated-mobile-access-desc' => 'Provides features for mobile providers that provide free access',
 20+ 'zero-rated-mobile-access-search' => 'Search',
 21+ 'zero-rated-mobile-access-language-options-wiki-page' => 'zero-rated-mobile-access-language-options',
 22+ 'zero-rated-mobile-access-carrier-options-wiki-page' => 'zero-rated-mobile-access-carrier-options',
 23+ 'zero-rated-mobile-access-language-selection' => 'All languages',
 24+ 'zero-rated-mobile-access-home-page-selection' => '$1 home page',
 25+ 'zero-rated-mobile-access-home-page-selection-text' => 'Or go to the home page in the following language:',
 26+ 'zero-rated-mobile-access-banner-text' => 'Free Wikipedia from $1',
 27+ 'zero-rated-mobile-access-banner-text-data-charges' => 'Data charges may apply continue: $1 or $2',
 28+ 'zero-rated-mobile-access-banner-text-data-charges-yes' => 'Yes',
 29+ 'zero-rated-mobile-access-banner-text-data-charges-no' => 'No',
 30+ 'zero-rated-mobile-access-click-to-view-image' => 'Click to view image of, "$1"...',
 31+);
 32+
 33+/** Message documentation (Message documentation)
 34+ * @author Patrick Reilly
 35+ */
 36+$messages['qqq'] = array(
 37+ 'zero-rated-mobile-access-desc' => '{{desc}}',
 38+ 'zero-rated-mobile-access-search' => 'Text for search action on the search button',
 39+ 'zero-rated-mobile-access-language-options-wiki-page' => 'The name of the wiki page in the MediaWiki namespace to store the country language data',
 40+ 'zero-rated-mobile-access-language-selection' => 'Text to show the user when they select a language option',
 41+ 'zero-rated-mobile-access-home-page-selection' => 'Name of language followed by text to show user in local link to Wikipedia',
 42+ 'zero-rated-mobile-access-home-page-selection-text' => 'Text to show user prior to selection of language option',
 43+ 'zero-rated-mobile-access-banner-text' => 'Text shown to users of various carriers with carrier name',
 44+ 'zero-rated-mobile-access-banner-text-data-charges' => 'Data charges notice to user before images are displayed
 45+* $1 = {{Msg-mw|zero-rated-mobile-access-banner-text-data-charges-yes}}
 46+* $2 = {{Msg-mw|zero-rated-mobile-access-banner-text-data-charges-no}}',
 47+ 'zero-rated-mobile-access-banner-text-data-charges-yes' => 'Text for accepting charges',
 48+ 'zero-rated-mobile-access-banner-text-data-charges-no' => 'Text for rejecting charges',
 49+ 'zero-rated-mobile-access-click-to-view-image' => 'Text for viewing an image link',
 50+);
 51+
 52+/** Japanese (日本語)
 53+ * @author Patrick Reilly
 54+ */
 55+$messages['ja'] = array (
 56+ 'zero-rated-mobile-access-desc' => 'ゼロ格モバイルアクセス',
 57+ 'zero-rated-mobile-access-search' => '検索する',
 58+);
 59+
Property changes on: branches/wmf/1.18wmf1/extensions/ZeroRatedMobileAccess/ZeroRatedMobileAccess.i18n.php
___________________________________________________________________
Added: svn:eol-style
160 + native

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r106907skeleton for extensionpreilly00:45, 21 December 2011
r108532Fix whitespace...reedy18:42, 10 January 2012

Status & tagging log