EBernhardson has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/384180 )

Change subject: Add opt out to relevance survey
......................................................................

Add opt out to relevance survey

* Opt-out for anonymous users is tracked in local storage, so
 is only handled on a best-effort basis.
* Opt-out for logged in users is tracked in the mediawiki user
 options so should be a strong guarantee.

Bug: T176428
Change-Id: Ic08d0362ea26beb2e1e6d996e4b48c46a14d9d15
---
M extension.json
M i18n/en.json
M i18n/qqq.json
M includes/ApiRelevanceSurvey.php
M modules/ext.wikimediaEvents.humanSearchRelevance.css
M modules/ext.wikimediaEvents.humanSearchRelevance.js
6 files changed, 83 insertions(+), 10 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikimediaEvents 
refs/changes/80/384180/1

diff --git a/extension.json b/extension.json
index 37bd3bf..290382b 100644
--- a/extension.json
+++ b/extension.json
@@ -19,7 +19,8 @@
                "relevancesurvey": 
"MediaWiki\\WikimediaEvents\\ApiRelevanceSurvey"
        },
        "DefaultUserOptions": {
-               "wme-relevance-filter": ""
+               "wme-relevance-filter": "",
+               "wme-relevance-optout": false
        },
        "Hooks": {
                "BeforeInitialize": [
@@ -166,7 +167,7 @@
                "schema.HumanSearchRelevance": {
                        "class": "ResourceLoaderSchemaModule",
                        "schema": "HumanSearchRelevance",
-                       "revision": 17320055
+                       "revision": 17322925
                },
                "ext.wikimediaEvents": {
                        "scripts": [
@@ -217,7 +218,8 @@
                                "wikimediaevents-humanrel-no",
                                "wikimediaevents-humanrel-unsure",
                                "wikimediaevents-humanrel-why",
-                               "wikimediaevents-humanrel-privacy-statement"
+                               "wikimediaevents-humanrel-privacy-statement",
+                               "wikimediaevents-humanrel-opt-out"
                        ],
                        "styles": [
                                "ext.wikimediaEvents.humanSearchRelevance.css"
diff --git a/i18n/en.json b/i18n/en.json
index 1916a3d..eddd96b 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -19,5 +19,6 @@
        "wikimediaevents-humanrel-no": "No",
        "wikimediaevents-humanrel-unsure": "I don't know",
        "wikimediaevents-humanrel-why": "Why we are asking this?",
-       "wikimediaevents-humanrel-privacy-statement": "Privacy Statement"
+       "wikimediaevents-humanrel-privacy-statement": "Privacy Statement",
+       "wikimediaevents-humanrel-opt-out": "Opt out of survey"
 }
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 05fd94e..b3d5488 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -22,5 +22,6 @@
        "wikimediaevents-humanrel-no": "Negative answer to articles relevance 
to a search query.\n\nAppears with the question: 
{{msg-mw|wikimediaevents-humanrel-question-c}}\n\n{{Identical|No}}",
        "wikimediaevents-humanrel-unsure": "Indecisive answer to articles 
relevance to a search query.\n\nSee also: 
{{msg-mw|wikimediaevents-humanrel-question-c}}, 
{{msg-mw|wikimediaevents-humanrel-yes}}, 
{{msg-mw|wikimediaevents-humanrel-no}}",
        "wikimediaevents-humanrel-why": "Link text to wiki page describing the 
purpose of the survey.",
-       "wikimediaevents-humanrel-privacy-statement": "Text for link to the 
survey privacy statement."
+       "wikimediaevents-humanrel-privacy-statement": "Text for link to the 
survey privacy statement.",
+       "wikimediaevents-humanrel-opt-out": "Text for link to opt out (never 
see again) the search relevance survey."
 }
diff --git a/includes/ApiRelevanceSurvey.php b/includes/ApiRelevanceSurvey.php
index 48b7424..c547732 100644
--- a/includes/ApiRelevanceSurvey.php
+++ b/includes/ApiRelevanceSurvey.php
@@ -4,12 +4,16 @@
 
 use ApiBase;
 use InvalidArgumentException;
+use MediaWiki\Logger\LoggerFactory;
+use MWException;
 use Title;
 use User;
 
 class ApiRelevanceSurvey extends ApiBase {
        // User option that stores the per-user bloom filter
        const USER_OPTION_FILTER = 'wme-relevance-filter';
+       // User option to opt out of surveys
+       const USER_OPTION_OPTOUT = 'wme-relevance-optout';
 
        // A bloom filter with 180 bytes and 6 hashes gives a false positive 
rate
        // of 0.01% at 58 items, 1% at 150 items, and 10% at 275 items.
@@ -18,6 +22,29 @@
 
        public function execute() {
                $params = $this->extractRequestParams();
+
+               $user = $this->getUser();
+               if ( $params['optout'] ) {
+                       if ( $user->isAnon() ) {
+                               $this->dieWithError( 
'apierror-musbeloggedin-generic' );
+                       }
+                       // There is a small possibility of CAS errors if 
multiple requests
+                       // are trying to change user options. Make the window 
as small as
+                       // possible since the user would really prefer we not 
forget about
+                       // their opt out preference.
+                       $user = User::newFromId( $user->getId() );
+                       $user->load( User::READ_LATEST );
+                       $user->setOption( self::USER_OPTION_OPTOUT, '1' );
+                       $user->saveSettings();
+                       $this->applyResult( false );
+                       return;
+               }
+
+               if ( $user->getOption( self::USER_OPTION_OPTOUT ) ) {
+                       $this->applyResult( false );
+                       return;
+               }
+
                $title = Title::newFromText( $params['title'] );
                if ( !$title ) {
                        $this->dieWithError( [ 'apierror-invalidtitle', 
$params['title'] ] );
@@ -101,6 +128,9 @@
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true,
                        ],
+                       'optout' => [
+                               ApiBase::PARAM_TYPE => 'boolean',
+                       ],
                ];
        }
 }
diff --git a/modules/ext.wikimediaEvents.humanSearchRelevance.css 
b/modules/ext.wikimediaEvents.humanSearchRelevance.css
index 1e9b8fb..1f670b0 100644
--- a/modules/ext.wikimediaEvents.humanSearchRelevance.css
+++ b/modules/ext.wikimediaEvents.humanSearchRelevance.css
@@ -22,3 +22,10 @@
        /* Force the first footer anchor onto it's own line */
        display: block;
 }
+
+/* Center the buttons and footer */
+.mw-wme-humanrel-question > .oo-ui-buttonGroupWidget,
+.mw-wme-humanrel-question > .footer {
+       text-align: center;
+       width: 100%;
+}
diff --git a/modules/ext.wikimediaEvents.humanSearchRelevance.js 
b/modules/ext.wikimediaEvents.humanSearchRelevance.js
index 8bdb789..14f043d 100644
--- a/modules/ext.wikimediaEvents.humanSearchRelevance.js
+++ b/modules/ext.wikimediaEvents.humanSearchRelevance.js
@@ -1,6 +1,9 @@
 ( function ( mw, $ ) {
        'use strict';
 
+       var sampleRate,
+               optOutKey = 'wme-humrel-optout';
+
        function sample( acceptPercentage ) {
                var rand = mw.user.generateRandomSessionId(),
                        // take the first 52 bits of the rand value to match js
@@ -30,11 +33,24 @@
        // The config value is coded into the page output and cached in varnish.
        // That means any changes to sampling rates or pages chosen will take 
up to
        // a week to propogate into the wild unless explicitly purged.
-       var sampleRate = mw.config.get( 'wgWMESearchRelevancePages' );
+       sampleRate = mw.config.get( 'wgWMESearchRelevancePages' );
 
        // This page view not chosen for sampling
        if ( !sample( sampleRate ) ) {
                return;
+       }
+
+       function applyOptOut() {
+               if ( mw.user.isAnon() ) {
+                       // best we can do for anon users.
+                       mw.storage.set( optOutKey, '1' );
+               } else {
+                       new mw.Api().post( {
+                               action: 'relevancesurvey',
+                               title: mw.config.get( 'wgTitle' ),
+                               optout: true
+                       } );
+               }
        }
 
        function canAskQuestion() {
@@ -42,11 +58,17 @@
                        timeout = mw.storage.get( timeoutKey ),
                        now = Date.now();
 
+               // User has previously opted out
+               if ( mw.storage.get( optOutKey ) ) {
+                       return false;
+               }
+
                // Don't show the survey to same browser for 2 days, to prevent 
annoying users
                if ( timeout && timeout > now ) {
                        // User has seen the survey recently
                        return false;
                }
+
                // If we can't record that the survey shouldn't be duplicated, 
just
                // opt them out of the survey all together.
                if ( !mw.storage.set( timeoutKey, now + 2 * 86400000 ) ) {
@@ -77,7 +99,12 @@
                                $( '<a>', {
                                        href: 
'//wikimediafoundation.org/wiki/Search_Relevance_Survey_Privacy_Statement',
                                        target: '_blank'
-                               } ).text( mw.message( 
'wikimediaevents-humanrel-privacy-statement' ) )
+                               } ).text( mw.message( 
'wikimediaevents-humanrel-privacy-statement' ) ),
+                               // TODO: Could be done with css instead i 
suppose?
+                               document.createTextNode( ' | ' ),
+                               $( '<a>' )
+                                       .text( mw.message( 
'wikimediaevents-humanrel-opt-out' ) )
+                                       .on( 'click', function () { onClick( 
'optout' ); } )
                        );
 
                return $( '<p>' ).attr( {
@@ -106,7 +133,12 @@
                                        } );
                                } );
                        },
-                       content = buildContent( query, logEvent );
+                       content = buildContent( query, function ( clicked ) {
+                               if ( clicked === 'optout' ) {
+                                       applyOptOut();
+                               }
+                               logEvent( clicked );
+                       } );
 
                // we need a longer timeout than notification provides manually,
                // so create our out key. While at it extend the timeout from
@@ -131,7 +163,8 @@
                        return originalClose();
                };
 
-               // Prevent clicks in footer from closing notification.
+               // Prevent clicks in footer from closing notification. Opt-out 
will
+               // close the notification directly.
                content.find( '.footer' ).on( 'click', function ( event ) {
                        event.stopPropagation();
                        // These clicks open some external page in a new tab, 
restart the
@@ -175,5 +208,4 @@
                } );
                // When debugging show the survey immediately
        }, mw.Debug ? 0 : 60000 );
-
 }( mediaWiki, jQuery ) );

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic08d0362ea26beb2e1e6d996e4b48c46a14d9d15
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikimediaEvents
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <ebernhard...@wikimedia.org>

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

Reply via email to