Florianschmidtwelzow has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/311175

Change subject: WIP: Add option to limit the cookie warning to specific regions
......................................................................

WIP: Add option to limit the cookie warning to specific regions

With this change, CookieWarning gets two new ways to limit the warning
bar to users of specific (configurable) regions. Based on the geo location
service (which can be configured, too, defaults to freegeoip.net), the
extension will try to get the region of the user (based on the IP address)
and checks it against the configured regions.

With the configuration variable $wgCookieWarningGeoIPLookup, the wiki sysadmin
can configure, if the lookup should be done with PHP (the timeout for the
request is hardcoded to 2 sedonds max), which will save the paylod sent to
the user, or with JavaScript, which will be asynchronous.

Deactivating this feature is easily done by simply setting the configured 
regions
to false, instead of an object.

Bug: T145780
Change-Id: I4d9371b8608ef270c11c42bdb3a773675977ab3a
---
M extension.json
M includes/CookieWarning.hooks.php
A includes/GeoLocation.php
A resources/ext.CookieWarning.geolocation/cookiePolicy.js
A resources/ext.CookieWarning.geolocation/styles.css
5 files changed, 300 insertions(+), 7 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CookieWarning 
refs/changes/75/311175/1

diff --git a/extension.json b/extension.json
index 722db7f..9a2cfa7 100644
--- a/extension.json
+++ b/extension.json
@@ -22,11 +22,65 @@
                ],
                "GetPreferences": [
                        "CookieWarningHooks::onGetPreferences"
+               ],
+               "ResourceLoaderGetConfigVars": [
+                       "CookieWarningHooks::onResourceLoaderGetConfigVars"
                ]
        },
        "config": {
                "CookieWarningEnabled": false,
-               "CookieWarningMoreUrl": ""
+               "CookieWarningMoreUrl": "",
+               "CookieWarningGeoIPServiceURL": "//freegeoip.net/json/",
+               "CookieWarningGeoIPLookup": "php",
+               "CookieWarningForCountryCodes": {
+                       "EU": "Europe",
+                       "AD": "Andorra",
+                       "AL": "Albania",
+                       "AT": "Austria",
+                       "BA": "Bosnia and Herzegovina",
+                       "BE": "Belgium",
+                       "BG": "Bulgaria",
+                       "BY": "Belarus",
+                       "CH": "Switzerland",
+                       "CS": "Serbia and Montenegro",
+                       "CZ": "Czech Republic",
+                       "DE": "Germany",
+                       "DK": "Denmark",
+                       "EE": "Estonia",
+                       "ES": "Spain",
+                       "FI": "Finland",
+                       "FO": "Faroe Islands",
+                       "FR": "France",
+                       "FX": "France, Metropolitan",
+                       "GB": "United Kingdom",
+                       "GI": "Gibraltar",
+                       "GR": "Greece",
+                       "HR": "Croatia",
+                       "HU": "Hungary",
+                       "IE": "Ireland",
+                       "IS": "Iceland",
+                       "IT": "Italy",
+                       "LI": "Liechtenstein",
+                       "LT": "Lithuania",
+                       "LU": "Luxembourg",
+                       "LV": "Latvia",
+                       "MC": "Monaco",
+                       "MD": "Moldova, Republic of",
+                       "MK": "Macedonia",
+                       "MT": "Malta",
+                       "NL": "Netherlands",
+                       "NO": "Norway",
+                       "PL": "Poland",
+                       "PT": "Portugal",
+                       "RO": "Romania",
+                       "SE": "Sweden",
+                       "SI": "Slovenia",
+                       "SJ": "Svalbard and Jan Mayen",
+                       "SK": "Slovakia",
+                       "SM": "San Marino",
+                       "UA": "Ukraine",
+                       "VA": "Holy See (Vatican City State)"
+               }
        },
        "ResourceModules": {
                "ext.CookieWarning": {
@@ -47,6 +101,22 @@
                                "mobile",
                                "desktop"
                        ]
+               },
+               "ext.CookieWarning.geolocation": {
+                       "scripts": 
"resources/ext.CookieWarning.geolocation/cookiePolicy.js",
+                       "dependencies": "ext.CookieWarning",
+                       "targets": [
+                               "mobile",
+                               "desktop"
+                       ]
+               },
+               "ext.CookieWarning.geolocation.styles": {
+                       "position": "top",
+                       "styles": 
"resources/ext.CookieWarning.geolocation/styles.css",
+                       "targets": [
+                               "mobile",
+                               "desktop"
+                       ]
                }
        },
        "ResourceFileModulePaths": {
@@ -54,7 +124,8 @@
                "remoteExtPath": "CookieWarning"
        },
        "AutoloadClasses": {
-               "CookieWarningHooks": "includes/CookieWarning.hooks.php"
+               "CookieWarningHooks": "includes/CookieWarning.hooks.php",
+               "GeoLocation": "includes/GeoLocation.php"
        },
        "ConfigRegistry": {
                "cookiewarning": "GlobalVarConfig::newInstance"
diff --git a/includes/CookieWarning.hooks.php b/includes/CookieWarning.hooks.php
index 6826bd3..ae1b220 100644
--- a/includes/CookieWarning.hooks.php
+++ b/includes/CookieWarning.hooks.php
@@ -1,6 +1,7 @@
 <?php
 
 class CookieWarningHooks {
+       private static $inConfiguredRegion;
        /**
         * SkinTemplateOutputPageBeforeExec hook handler.
         *
@@ -13,7 +14,7 @@
                SkinTemplate &$sk, QuickTemplate &$tpl
        ) {
                // Config instance of CookieWarning
-               $conf = ConfigFactory::getDefaultInstance()->makeConfig( 
'cookiewarning' );
+               $conf = self::getConfig();
                $moreLink = '';
                // if a "more information" URL was configured, add a link to it 
in the cookiewarning
                // information bar
@@ -60,9 +61,42 @@
         */
        public static function onBeforePageDisplay( OutputPage $out ) {
                if ( self::showWarning( $out->getContext() ) ) {
-                       $out->addModuleStyles( array( 
'ext.CookieWarning.styles' ) );
-                       $out->addModules( array( 'ext.CookieWarning' ) );
+                       $moduleStyles = array( 'ext.CookieWarning.styles' );
+                       $modules = array( 'ext.CookieWarning' );
+                       if ( self::getConfig()->get( 'CookieWarningGeoIPLookup' 
) === 'js' ) {
+                               $modules[] = 'ext.CookieWarning.geolocation';
+                               $moduleStyles[] = 
'ext.CookieWarning.geolocation.styles';
+                       }
+                       $out->addModules( $modules );
+                       $out->addModuleStyles( $moduleStyles );
                }
+       }
+
+       /**
+        * ResourceLoaderGetConfigVars hook handler.
+        *
+        * @param array $vars
+        */
+       public static function onResourceLoaderGetConfigVars( array &$vars ) {
+               $conf = self::getConfig();
+               if (
+                       $conf->get( 'CookieWarningGeoIPLookup' ) === 'js' &&
+                       is_array( $conf->get( 'CookieWarningForCountryCodes' ) )
+               ) {
+                       $vars += [
+                               'wgCookieWarningGeoIPServiceURL' => $conf->get( 
'CookieWarningGeoIPServiceURL' ),
+                               'wgCookieWarningForCountryCodes' => $conf->get( 
'CookieWarningForCountryCodes' ),
+                       ];
+               }
+       }
+
+       /**
+        * Retruns the Config object for the CookieWarning extension.
+        *
+        * @return Config
+        */
+       private static function getConfig() {
+               return ConfigFactory::getDefaultInstance()->makeConfig( 
'cookiewarning' );
        }
 
        /**
@@ -74,14 +108,18 @@
         */
        private static function showWarning( IContextSource $context ) {
                $user = $context->getUser();
-               $conf = ConfigFactory::getDefaultInstance()->makeConfig( 
'cookiewarning' );
+               $conf = self::getConfig();
                if (
                        // if enabled in LocalSettings.php
                        $conf->get( 'CookieWarningEnabled' ) &&
                        // if not already dismissed by this user (and saved in 
the user prefs)
                        !$user->getBoolOption( 'cookiewarning_dismissed', false 
) &&
                        // if not already dismissed by this user (and saved in 
the browser cookies)
-                       !$context->getRequest()->getCookie( 
'cookiewarning_dismissed' )
+                       !$context->getRequest()->getCookie( 
'cookiewarning_dismissed' ) &&
+                       (
+                               $conf->get( 'CookieWarningGeoIPLookup' ) === 
'js' ||
+                               self::inConfiguredRegion( $context, $conf )
+                       )
                ) {
                        return true;
                }
@@ -89,6 +127,36 @@
        }
 
        /**
+        * Checks, if the user is in one of the configured regions.
+        *
+        * @TODO: This function or the function users should set the cookie or 
user option, if this
+        * function returns false to avoid a location lookup on each request.
+        * @param IContextSource $context
+        * @param Config $conf
+        * @return bool
+        */
+       private static function inConfiguredRegion( IContextSource $context, 
Config $conf ) {
+               if ( self::$inConfiguredRegion === null ) {
+                       if ( !$conf->get( 'CookieWarningForCountryCodes' ) ) {
+                               self::$inConfiguredRegion = true;
+                       } else {
+                               $geoLocation = new GeoLocation;
+                               $located = $geoLocation
+                                       ->setConfig( $conf )
+                                       ->setIP( 
$context->getRequest()->getIP() )
+                                       ->locate();
+                               if ( !$located ) {
+                                       self::$inConfiguredRegion = true;
+                               } else {
+                                       self::$inConfiguredRegion = 
array_key_exists( $geoLocation->getCountryCode(),
+                                               $conf->get( 
'CookieWarningForCountryCodes' ) );
+                               }
+                       }
+               }
+               return self::$inConfiguredRegion;
+       }
+
+       /**
         * GetPreferences hook handler
         *
         * @see https://www.mediawiki.org/wiki/Manual:Hooks/GetPreferences
diff --git a/includes/GeoLocation.php b/includes/GeoLocation.php
new file mode 100644
index 0000000..a812259
--- /dev/null
+++ b/includes/GeoLocation.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * GeoLocation implementation
+ */
+
+/**
+ * Implements the GeoLocation class, which allows to locate the user based on 
the IP address.
+ */
+class GeoLocation {
+       private $ip;
+       private $config;
+       private $countryCode;
+
+       /**
+        * Set the IP address you want to locate.
+        *
+        * @param string $ip A valid IP address
+        * @return $this
+        */
+       public function setIP( $ip ) {
+               if ( !IP::isValid( $ip ) ) {
+                       throw new InvalidArgumentException( "$ip is not a valid 
IP address." );
+               }
+               $this->ip = $ip;
+
+               return $this;
+       }
+
+       /**
+        * Returns the IP address.
+        *
+        * @return null|string NULL if the address is not set so far, string 
otherwise.
+        */
+       public function getIP() {
+               return $this->ip;
+       }
+
+       /**
+        * Sets the Config object used by this class.
+        *
+        * @param Config $config
+        * @return $this
+        */
+       public function setConfig( Config $config ) {
+               $this->config = $config;
+
+               return $this;
+       }
+
+       /**
+        * Returns the country code, if the last call to self::locate() 
returned true. Otherwise, NULL.
+        *
+        * @return null|string
+        */
+       public function getCountryCode() {
+               return $this->countryCode;
+       }
+
+       /**
+        * Tries to locate the IP address set with self::setIP() using the 
geolocation service
+        * configured with the $wgCookieWarningGeoIPServiceURL configuration 
variable. If the config
+        * isn't set, this function returns NULL. If the config is set, but the 
URL is invalid or an
+        * other problem occures which resulted in a failed locating process, 
this function returns
+        * false, otherwise it returns true.
+        *
+        * @return bool|null NULL if no geolocation service configured, false 
on error, true otherwise.
+        */
+       public function locate() {
+               $this->countryCode = null;
+               if ( $this->ip === null ) {
+                       throw new RuntimeException(
+                               'No IP address set, locating now would return 
the servers location.' );
+               }
+               if ( $this->config === null ) {
+                       throw new RuntimeException(
+                               'You need to set the Config object first, 
before you can locate an IP address.' );
+               }
+               if ( !$this->config->get( 'CookieWarningGeoIPServiceURL' ) ) {
+                       return null;
+               }
+               $requestUrl = $this->config->get( 
'CookieWarningGeoIPServiceURL' );
+               if ( substr( $requestUrl, -1) !== '/' ) {
+                       $requestUrl .= '/';
+               }
+               $json = Http::get( $requestUrl . $this->getIP(), array(
+                       'timeout' => '2'
+               ) );
+               if ( !$json ) {
+                       return false;
+               }
+               $returnObject = json_decode( $json );
+               if ( $returnObject === null || !property_exists( $returnObject, 
'country_code' ) ) {
+                       return false;
+               }
+               $this->countryCode = $returnObject->country_code;
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/resources/ext.CookieWarning.geolocation/cookiePolicy.js 
b/resources/ext.CookieWarning.geolocation/cookiePolicy.js
new file mode 100644
index 0000000..4c82437
--- /dev/null
+++ b/resources/ext.CookieWarning.geolocation/cookiePolicy.js
@@ -0,0 +1,53 @@
+/* global Geo, mediaWiki */
+( function ( mw, $ ) {
+       'use strict';
+       var geoLocation;
+
+       geoLocation = {
+               /**
+                * @return string Two-letter country code
+                */
+               getCountryCode: function () {
+                       /**
+                        * safe fallback -- if geolocation fails, display the 
notice anyway
+                        */
+                       var countryCode = 'EU';
+
+                       if ( !$.cookie( 'euCookieWarningCountryCode' ) ) {
+                               // @see 
http://www.dwuser.com/education/content/web-services-made-practical-where-are-your-visitors-from/
+                               $.get( mw.config.get( 
'wgCookieWarningGeoIPServiceURL' ), function ( data ) {
+                                       // Get the country code
+                                       countryCode = data.country_code;
+                                       // Store the result in a cookie (ah, 
the sweet, sweet irony) to
+                                       // avoid hitting the geolocation 
service unnecessarily
+                                       $.cookie('euCookieWarningCountryCode', 
countryCode, {
+                                               domain: window.mw.config.get( 
'wgCookieDomain' ),
+                                               path: '/',
+                                               expires: 30
+                                       });
+                               }, 'jsonp');
+                       } else if ($.cookie('euCookieWarningCountryCode') !== 
null) {
+                               countryCode = 
$.cookie('euCookieWarningCountryCode');
+                       }
+
+                       return countryCode;
+               },
+
+               /**
+                * Check if the supplied country code is that of a configured 
region.
+                *
+                * @return {boolean}
+                */
+               isInRegion: function () {
+                       return mw.config.get( 'wgCookieWarningForCountryCodes' 
).hasOwnProperty( this.getCountryCode() );
+               }
+       };
+
+       $( function () {
+               if ( geoLocation.isInRegion() ) {
+                       $( '.mw-cookiewarning-container' ).show();
+               } else {
+                       $( '.mw-cookiewarning-container' ).detach();
+               }
+       } );
+}( mediaWiki, jQuery ) );
\ No newline at end of file
diff --git a/resources/ext.CookieWarning.geolocation/styles.css 
b/resources/ext.CookieWarning.geolocation/styles.css
new file mode 100644
index 0000000..2110993
--- /dev/null
+++ b/resources/ext.CookieWarning.geolocation/styles.css
@@ -0,0 +1,3 @@
+.mw-cookiewarning-container {
+    display: none;
+}
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/311175
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I4d9371b8608ef270c11c42bdb3a773675977ab3a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/CookieWarning
Gerrit-Branch: master
Gerrit-Owner: Florianschmidtwelzow <florian.schmidt.stargatewis...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to