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 |
1 | 48 | + 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( "&", "&", $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 |
1 | 813 | + 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 |
1 | 48 | + 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 |
1 | 60 | + native |